adding back several more extensions
This commit is contained in:
parent
58ed243ac0
commit
196337a7bc
@ -7,14 +7,14 @@
|
||||
"original_name": "Convert Vertical/Horizontal To Line",
|
||||
"original_id": "fablabchemnitz.de.convert_vertical_horizontal_to_line",
|
||||
"license": "GNU GPL v3",
|
||||
"license_url": "https://gitea.fablabchemnitz.de/FabLab_Chemnitz/mightyscape-1.X/src/branch/master/LICENSE",
|
||||
"license_url": "https://gitea.fablabchemnitz.de/FabLab_Chemnitz/mightyscape-1.2/src/branch/master/LICENSE",
|
||||
"comment": "Written by Mario Voigt",
|
||||
"source_url": "https://gitea.fablabchemnitz.de/FabLab_Chemnitz/mightyscape-1.X/src/branch/master/extensions/fablabchemnitz/convert_vertical_horizontal_to_line",
|
||||
"source_url": "https://gitea.fablabchemnitz.de/FabLab_Chemnitz/mightyscape-1.2/src/branch/master/extensions/fablabchemnitz/convert_vertical_horizontal_to_line",
|
||||
"fork_url": null,
|
||||
"documentation_url": "https://stadtfabrikanten.org/pages/viewpage.action?pageId=79626259",
|
||||
"inkscape_gallery_url": null,
|
||||
"main_authors": [
|
||||
"github.com/vmario89"
|
||||
"github.com/eridur-de"
|
||||
]
|
||||
}
|
||||
]
|
@ -9,13 +9,13 @@
|
||||
"license": "GNU GPL v3",
|
||||
"license_url": "https://github.com/chrille69/Inkscape-Extension-pathpoints2dots/blob/master/LICENSE",
|
||||
"comment": "",
|
||||
"source_url": "https://gitea.fablabchemnitz.de/FabLab_Chemnitz/mightyscape-1.X/src/branch/master/extensions/fablabchemnitz/dots_to_path_points",
|
||||
"source_url": "https://gitea.fablabchemnitz.de/FabLab_Chemnitz/mightyscape-1.2/src/branch/master/extensions/fablabchemnitz/dots_to_path_points",
|
||||
"fork_url": "https://github.com/chrille69/Inkscape-Extension-pathpoints2dots",
|
||||
"documentation_url": "https://stadtfabrikanten.org/display/IFM/Dots+To+Path+Points",
|
||||
"inkscape_gallery_url": null,
|
||||
"main_authors": [
|
||||
"github.com/chrille69",
|
||||
"github.com/vmario89"
|
||||
"github.com/eridur-de"
|
||||
]
|
||||
}
|
||||
]
|
@ -9,13 +9,13 @@
|
||||
"license": "GNU LGPL v2",
|
||||
"license_url": "https://inkscape.org/~MatheM/%E2%98%85simple-attribute-editor+1",
|
||||
"comment": "",
|
||||
"source_url": "https://gitea.fablabchemnitz.de/FabLab_Chemnitz/mightyscape-1.X/src/branch/master/extensions/fablabchemnitz/edit_attributes",
|
||||
"source_url": "https://gitea.fablabchemnitz.de/FabLab_Chemnitz/mightyscape-1.2/src/branch/master/extensions/fablabchemnitz/edit_attributes",
|
||||
"fork_url": "https://inkscape.org/~MatheM/%E2%98%85simple-attribute-editor+1",
|
||||
"documentation_url": "https://stadtfabrikanten.org/display/IFM/Edit+Attributes",
|
||||
"inkscape_gallery_url": null,
|
||||
"main_authors": [
|
||||
"inkscape.org/MatheM",
|
||||
"github.com/vmario89"
|
||||
"github.com/eridur-de"
|
||||
]
|
||||
}
|
||||
]
|
@ -10,14 +10,14 @@
|
||||
"original_name": "Filter By Length/Area",
|
||||
"original_id": "com.filter_by_length_area",
|
||||
"license": "GNU GPL v3",
|
||||
"license_url": "https://gitea.fablabchemnitz.de/FabLab_Chemnitz/mightyscape-1.X/src/branch/master/LICENSE",
|
||||
"license_url": "https://gitea.fablabchemnitz.de/FabLab_Chemnitz/mightyscape-1.2/src/branch/master/LICENSE",
|
||||
"comment": "",
|
||||
"source_url": "https://gitea.fablabchemnitz.de/FabLab_Chemnitz/mightyscape-1.X/src/branch/master/extensions/fablabchemnitz/filter_by_length_area",
|
||||
"source_url": "https://gitea.fablabchemnitz.de/FabLab_Chemnitz/mightyscape-1.2/src/branch/master/extensions/fablabchemnitz/filter_by_length_area",
|
||||
"fork_url": null,
|
||||
"documentation_url": "https://stadtfabrikanten.org/pages/viewpage.action?pageId=74645969",
|
||||
"inkscape_gallery_url": null,
|
||||
"main_authors": [
|
||||
"github.com/vmario89"
|
||||
"github.com/eridur-de"
|
||||
]
|
||||
}
|
||||
]
|
@ -0,0 +1,21 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<inkscape-extension xmlns="http://www.inkscape.org/namespace/inkscape/extension">
|
||||
<name>Filter To Layer</name>
|
||||
<id>fablabchemnitz.de.filter_to_layer</id>
|
||||
<param name="type" type="optiongroup" appearance="radio" gui-text="Filter to current layer:">
|
||||
<option>Add</option>
|
||||
<option>Remove</option>
|
||||
</param>
|
||||
<label>Filter from selected item: Apply only for the future draws and for selected item. Problem: you can't add more live effects to elements.</label>
|
||||
<effect needs-document="true">
|
||||
<object-type>all</object-type>
|
||||
<effects-menu>
|
||||
<submenu name="FabLab Chemnitz">
|
||||
<submenu name="Groups and Layers"/>
|
||||
</submenu>
|
||||
</effects-menu>
|
||||
</effect>
|
||||
<script>
|
||||
<command location="inx" interpreter="python">filter_to_layer.py</command>
|
||||
</script>
|
||||
</inkscape-extension>
|
82
extensions/fablabchemnitz/filter_to_layer/filter_to_layer.py
Normal file
82
extensions/fablabchemnitz/filter_to_layer/filter_to_layer.py
Normal file
@ -0,0 +1,82 @@
|
||||
#!/usr/bin/env python3
|
||||
'''
|
||||
This extension adds filters to current layer or removes filters from current layer
|
||||
|
||||
Copyright (C) 2012 Jabiertxo Arraiza, jabier.arraiza@marker.es
|
||||
|
||||
Version 0.3
|
||||
|
||||
TODO:
|
||||
Comment Better!!!
|
||||
|
||||
CHANGE LOG
|
||||
0.1 Start 30/07/2012
|
||||
|
||||
This program is free software; you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as published by
|
||||
the Free Software Foundation; either version 2 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 General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with this program; if not, write to the Free Software
|
||||
Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||
'''
|
||||
|
||||
import inkex
|
||||
import sys
|
||||
import re
|
||||
|
||||
class FilterToLayer(inkex.EffectExtension):
|
||||
|
||||
def add_arguments(self, pars):
|
||||
pars.add_argument('--type', default = 'Add', help = 'Add or remove filters to current layer')
|
||||
|
||||
def selectTop(self):
|
||||
selectedSorted = None
|
||||
if self.svg.selected is not None:
|
||||
for element in self.document.getroot().iter():
|
||||
if element.get("id") in self.svg.selection:
|
||||
selectedSorted = element
|
||||
return selectedSorted
|
||||
|
||||
def effect(self):
|
||||
svg = self.document.getroot()
|
||||
typeOperation = self.options.type
|
||||
xpathStr = '//sodipodi:namedview'
|
||||
namedview = svg.xpath(xpathStr, namespaces=inkex.NSS)
|
||||
idLayer = namedview[0].get('{http://www.inkscape.org/namespaces/inkscape}current-layer');
|
||||
xpathStr = '//svg:g[@id="'+idLayer+'"]'
|
||||
layer = svg.xpath(xpathStr, namespaces=inkex.NSS)
|
||||
|
||||
if typeOperation == "Add": #Add action
|
||||
element = self.selectTop()
|
||||
if element is not None:
|
||||
if element.get('style'):
|
||||
matchObj = re.search( r'filter:url\(#.*?[^\)]\)', element.get('style'), re.M|re.I)
|
||||
if matchObj:
|
||||
filter = matchObj.group()
|
||||
element.set('style',element.get('style').replace(filter,"").replace(";;",";"))
|
||||
if layer[0].get('style'):
|
||||
matchObj = re.search( r'filter:url\(#.*?[^\)]\)', layer[0].get('style'), re.M|re.I)
|
||||
if matchObj:
|
||||
element.set('style',element.get('style').replace(matchObj.group(),"").replace(";;",";"))
|
||||
style = layer[0].get('style')+ ";" + filter;
|
||||
layer[0].set('style',style.replace(";;",";"))
|
||||
else:
|
||||
layer[0].set('style',filter)
|
||||
else:
|
||||
inkex.utils.debug("Nothing selected")
|
||||
|
||||
else: #Remove action
|
||||
if layer[0].get('style'):
|
||||
matchObj = re.search( r'filter:url\(#.*?[^\)]\)', layer[0].get('style'), re.M|re.I)
|
||||
if matchObj:
|
||||
layer[0].set('style',layer[0].get('style').replace(matchObj.group(),"").replace(";;",";"))
|
||||
|
||||
if __name__ == '__main__':
|
||||
FilterToLayer().run()
|
21
extensions/fablabchemnitz/filter_to_layer/meta.json
Normal file
21
extensions/fablabchemnitz/filter_to_layer/meta.json
Normal file
@ -0,0 +1,21 @@
|
||||
[
|
||||
{
|
||||
"name": "Filter To Layer",
|
||||
"id": "fablabchemnitz.de.filter_to_layer",
|
||||
"path": "filter_to_layer",
|
||||
"dependent_extensions": null,
|
||||
"original_name": "Filter to layer",
|
||||
"original_id": "org.inkscape.filter.layer",
|
||||
"license": "GNU GPL v2",
|
||||
"license_url": "https://inkscape.org/~jabiertxof/%E2%98%85filter-layer",
|
||||
"comment": "",
|
||||
"source_url": "https://gitea.fablabchemnitz.de/FabLab_Chemnitz/mightyscape-1.2/src/branch/master/extensions/fablabchemnitz/filter_to_layer",
|
||||
"fork_url": "https://inkscape.org/~jabiertxof/%E2%98%85filter-layer",
|
||||
"documentation_url": "https://stadtfabrikanten.org/display/IFM/Filter+To+Layer",
|
||||
"inkscape_gallery_url": null,
|
||||
"main_authors": [
|
||||
"inkscape.org/jabiertxof",
|
||||
"github.com/eridur-de"
|
||||
]
|
||||
}
|
||||
]
|
28
extensions/fablabchemnitz/gpx_import/gpx_import.inx
Normal file
28
extensions/fablabchemnitz/gpx_import/gpx_import.inx
Normal file
@ -0,0 +1,28 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<inkscape-extension xmlns="http://www.inkscape.org/namespace/inkscape/extension">
|
||||
<name>GPX Import</name>
|
||||
<id>fablabchemnitz.de.gpx_import</id>
|
||||
<param name="tab" type="notebook">
|
||||
<page name="options" gui-text="Options">
|
||||
<param name="m" type="int" gui-text="Maximum width or height of the SVG in pixels" min="0" max="100000">3000</param>
|
||||
<param name="d" type="bool" gui-text="Drop single points" gui-description="Default: draw a circle with 1px diameter">true</param>
|
||||
<param name="r" type="bool" gui-text="Raw conversion" gui-description="Create on SVG path per track segment, don't try to combine paths that end with the starting piont of another path">true</param>
|
||||
<param name="j" type="bool" gui-text="Join all segments" gui-description="Join all segments to a big one in the order of the gpx file. This can create an oun-scattered path if the default combining algorthm does not work because there are no matching pints across segments (implies raw conversion)">true</param>
|
||||
</page>
|
||||
<page name="help" gui-text="Help">
|
||||
<label appearance="header">Homepage</label>
|
||||
<label appearance="url">https://efossils.somxslibres.net/fossil/user/mono/repository/inkgpx2svg/index</label>
|
||||
<label appearance="header">based on gpx2svg</label>
|
||||
<label appearance="url">https://nasauber.de/opensource/gpx2svg/</label>
|
||||
</page>
|
||||
</param>
|
||||
<input>
|
||||
<extension>.gpx</extension>
|
||||
<mimetype>application/gpx+xml</mimetype>
|
||||
<filetypename>GPS eXchange Format (*.gpx)</filetypename>
|
||||
<filetypetooltip>Import GPX Format</filetypetooltip>
|
||||
</input>
|
||||
<script>
|
||||
<command location="inx" interpreter="python">gpx_import.py</command>
|
||||
</script>
|
||||
</inkscape-extension>
|
379
extensions/fablabchemnitz/gpx_import/gpx_import.py
Normal file
379
extensions/fablabchemnitz/gpx_import/gpx_import.py
Normal file
@ -0,0 +1,379 @@
|
||||
#!/usr/bin/env python3
|
||||
|
||||
# Copyright (c) 2012-2018 Tobias Leupold <tobias.leupold@gmx.de>
|
||||
#
|
||||
# gpx2svg - Convert GPX formatted geodata to Scalable Vector Graphics (SVG)
|
||||
#
|
||||
# This program is free software; you can redistribute it and/or modify it
|
||||
# under the terms of the GNU General Public License as published by the Free
|
||||
# Software Foundation in version 2 of the License.
|
||||
#
|
||||
# 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 General Public License
|
||||
# for more details.
|
||||
#
|
||||
# You should have received a copy of the GNU General Public License along
|
||||
# with this program; if not, write to the Free Software Foundation, Inc.,
|
||||
# 59 Temple Place, Suite 330, Boston, MA 02111-1307, USA.
|
||||
#
|
||||
# modified by monomono@disroot.org at 2019-08-05 for use on inkscape extension,
|
||||
# 3to2 python converter and adjust parser_options for inkscape compatibility.
|
||||
|
||||
from __future__ import division
|
||||
from __future__ import absolute_import
|
||||
from io import open
|
||||
__version__ = u'@VERSION@'
|
||||
|
||||
import argparse
|
||||
import sys
|
||||
import math
|
||||
from xml.dom.minidom import parse as parseXml
|
||||
from os.path import abspath
|
||||
|
||||
def parseGpx(gpxFile):
|
||||
u"""Get the latitude and longitude data of all track segments in a GPX file"""
|
||||
|
||||
if gpxFile == u'/dev/stdin':
|
||||
gpxFile = sys.stdin
|
||||
|
||||
# Get the XML information
|
||||
try:
|
||||
gpx = parseXml(gpxFile)
|
||||
except IOError as error:
|
||||
print (sys.stderr, u'Error while reading file: {}. Terminating.'.format(error))
|
||||
sys.exit(1)
|
||||
except:
|
||||
print (sys.stderr, u'Error while parsing XML data:')
|
||||
print (sys.stderr, sys.exc_info())
|
||||
print (sys.stderr, u'Terminating.')
|
||||
sys.exit(1)
|
||||
|
||||
# Iterate over all tracks, track segments and points
|
||||
gpsData = []
|
||||
for track in gpx.getElementsByTagName(u'trk'):
|
||||
for trackseg in track.getElementsByTagName(u'trkseg'):
|
||||
trackSegData = []
|
||||
for point in trackseg.getElementsByTagName(u'trkpt'):
|
||||
trackSegData.append(
|
||||
(float(point.attributes[u'lon'].value), float(point.attributes[u'lat'].value))
|
||||
)
|
||||
# Leave out empty segments
|
||||
if(trackSegData != []):
|
||||
gpsData.append(trackSegData)
|
||||
|
||||
return gpsData
|
||||
|
||||
def calcProjection(gpsData):
|
||||
u"""Calculate a plane projection for a GPS dataset"""
|
||||
|
||||
projectedData = []
|
||||
for segment in gpsData:
|
||||
projectedSegment = []
|
||||
for coord in segment:
|
||||
# At the moment, we only have the Mercator projection
|
||||
projectedSegment.append(mercatorProjection(coord))
|
||||
projectedData.append(projectedSegment)
|
||||
|
||||
return projectedData
|
||||
|
||||
def mercatorProjection(coord):
|
||||
u"""Calculate the Mercator projection of a coordinate pair"""
|
||||
|
||||
# Assuming we're on earth, we have (according to GRS 80):
|
||||
r = 6378137.0
|
||||
|
||||
# As long as meridian = 0 and can't be changed, we don't need:
|
||||
# meridian = meridian * math.pi / 180.0
|
||||
# x = r * ((coord[0] * math.pi / 180.0) - meridian)
|
||||
|
||||
# Instead, we use this simplified version:
|
||||
x = r * coord[0] * math.pi / 180.0
|
||||
y = r * math.log(math.tan((math.pi / 4.0) + ((coord[1] * math.pi / 180.0) / 2.0)))
|
||||
return x, y
|
||||
|
||||
def moveProjectedData(gpsData):
|
||||
u"""Move a dataset to 0,0 and return it with the resulting width and height"""
|
||||
|
||||
# Find the minimum and maximum x and y coordinates
|
||||
minX = maxX = gpsData[0][0][0]
|
||||
minY = maxY = gpsData[0][0][1]
|
||||
for segment in gpsData:
|
||||
for coord in segment:
|
||||
if coord[0] < minX:
|
||||
minX = coord[0]
|
||||
if coord[0] > maxX:
|
||||
maxX = coord[0]
|
||||
if coord[1] < minY:
|
||||
minY = coord[1]
|
||||
if coord[1] > maxY:
|
||||
maxY = coord[1]
|
||||
|
||||
# Move the GPS data to 0,0
|
||||
movedGpsData = []
|
||||
for segment in gpsData:
|
||||
movedSegment = []
|
||||
for coord in segment:
|
||||
movedSegment.append((coord[0] - minX, coord[1] - minY))
|
||||
movedGpsData.append(movedSegment)
|
||||
|
||||
# Return the moved data and it's width and height
|
||||
return movedGpsData, maxX - minX, maxY - minY
|
||||
|
||||
def searchCircularSegments(gpsData):
|
||||
u"""Splits a GPS dataset to tracks that are circular and other tracks"""
|
||||
|
||||
circularSegments = []
|
||||
straightSegments = []
|
||||
|
||||
for segment in gpsData:
|
||||
if segment[0] == segment[len(segment) - 1]:
|
||||
circularSegments.append(segment)
|
||||
else:
|
||||
straightSegments.append(segment)
|
||||
|
||||
return circularSegments, straightSegments
|
||||
|
||||
def combineSegmentPairs(gpsData):
|
||||
u"""Combine segment pairs to one bigger segment"""
|
||||
|
||||
combinedData = []
|
||||
|
||||
# Walk through the GPS data and search for segment pairs
|
||||
# that end with the starting point of another track
|
||||
while len(gpsData) > 0:
|
||||
# Get one segment from the source GPS data
|
||||
firstTrackData = gpsData.pop()
|
||||
foundMatch = False
|
||||
|
||||
# Try to find a matching segment
|
||||
for i in xrange(len(gpsData)):
|
||||
if firstTrackData[len(firstTrackData) - 1] == gpsData[i][0]:
|
||||
# There is a matching segment, so break here
|
||||
foundMatch = True
|
||||
break
|
||||
|
||||
if foundMatch == True:
|
||||
# We found a pair of segments with one shared point, so pop the data of the second
|
||||
# segment from the source GPS data and create a new segment containing all data, but
|
||||
# without the overlapping point
|
||||
firstTrackData.pop()
|
||||
combinedData.append(firstTrackData + gpsData[i])
|
||||
gpsData.pop(i)
|
||||
else:
|
||||
# No segment with a shared point was found, so just append the data to the output
|
||||
combinedData.append(firstTrackData)
|
||||
|
||||
return searchCircularSegments(combinedData)
|
||||
|
||||
def combineSegments(gpsData):
|
||||
u"""Combine all segments of a GPS dataset that can be combined"""
|
||||
|
||||
# Search for circular segments. We can't combine them with any other segment.
|
||||
circularSegments, remainingSegments = searchCircularSegments(gpsData)
|
||||
|
||||
# Search for segments that can be combined
|
||||
while True:
|
||||
# Look how many tracks we have now
|
||||
segmentsBefore = len(remainingSegments)
|
||||
|
||||
# Search for segments that can be combined
|
||||
newCircularSegments, remainingSegments = combineSegmentPairs(remainingSegments)
|
||||
|
||||
# Add newly found circular segments to processedSegments -- they can't be used anymore
|
||||
circularSegments = circularSegments + newCircularSegments
|
||||
|
||||
if segmentsBefore == len(remainingSegments):
|
||||
# combineSegmentPairs() did not reduce the number of tracks anymore,
|
||||
# so we can't combine more tracks and can stop here
|
||||
break
|
||||
|
||||
return circularSegments + remainingSegments
|
||||
|
||||
def chronologyJoinSegments(gpsData):
|
||||
u"""Join all segments to a big one in the order defined by the GPX file."""
|
||||
joinedSegment = []
|
||||
for segment in gpsData:
|
||||
joinedSegment += segment
|
||||
return [joinedSegment]
|
||||
|
||||
def scaleCoords(coord, height, scale):
|
||||
u"""Return a scaled pair of coordinates"""
|
||||
return coord[0] * scale, (coord[1] * -1 + height) * scale
|
||||
|
||||
def generateScaledSegment(segment, height, scale):
|
||||
u"""Create the coordinate part of an SVG path string from a GPS data segment"""
|
||||
for coord in segment:
|
||||
yield scaleCoords(coord, height, scale)
|
||||
|
||||
def writeSvgData(gpsData, width, height, maxPixels, dropSinglePoints, outfile):
|
||||
u"""Output the SVG data -- quick 'n' dirty, without messing around with dom stuff ;-)"""
|
||||
|
||||
# Calculate the scale factor we need to fit the requested maximal output size
|
||||
if width <= maxPixels and height <= maxPixels:
|
||||
scale = 1
|
||||
elif width > height:
|
||||
scale = maxPixels / width
|
||||
else:
|
||||
scale = maxPixels / height
|
||||
|
||||
# Open the requested output file or map to /dev/stdout
|
||||
if outfile != u'/dev/stdout':
|
||||
try:
|
||||
fp = open(outfile, u'w')
|
||||
except IOError as error:
|
||||
print (sys.stderr, u"Can't open output file: {}. Terminating.".format(error))
|
||||
sys.exit(1)
|
||||
else:
|
||||
fp = sys.stdout
|
||||
|
||||
# Header data
|
||||
fp.write( u'<?xml version="1.0" encoding="UTF-8" standalone="no"?>\n')
|
||||
fp.write((u'<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" '
|
||||
u'"http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd">\n'))
|
||||
fp.write( u'<!-- Created with gpx2svg {} -->\n'.format(__version__))
|
||||
fp.write((u'<svg xmlns="http://www.w3.org/2000/svg" version="1.1" '
|
||||
u'width="{}px" height="{}px">\n').format(width * scale, height * scale))
|
||||
|
||||
# Process all track segments and generate ids and path drawing commands for them
|
||||
|
||||
# First, we split the data to circular and straight segments
|
||||
circularSegments, straightSegments = searchCircularSegments(gpsData)
|
||||
realCircularSegments = []
|
||||
singlePoints = []
|
||||
for segment in circularSegments:
|
||||
# We can leave out the last point, because it's equal to the first one
|
||||
segment.pop()
|
||||
if len(segment) == 1:
|
||||
# It's a single point
|
||||
if dropSinglePoints == False:
|
||||
# We want to keep single points, so add it to singlePoints
|
||||
singlePoints.append(segment)
|
||||
else:
|
||||
realCircularSegments.append(segment)
|
||||
|
||||
circularSegments = realCircularSegments
|
||||
|
||||
# Draw single points if requested
|
||||
if len(singlePoints) > 0:
|
||||
fp.write(u'<g>\n')
|
||||
for segment in singlePoints:
|
||||
x, y = scaleCoords(segment[0], height, scale)
|
||||
fp.write(
|
||||
u'<circle cx="{}" cy="{}" r="0.5" style="stroke:none;fill:black"/>\n'.format(x, y)
|
||||
)
|
||||
fp.write(u'</g>\n')
|
||||
|
||||
# Draw all circular segments
|
||||
if len(circularSegments) > 0:
|
||||
fp.write(u'<g>\n')
|
||||
for segment in circularSegments:
|
||||
fp.write(u'<path d="M')
|
||||
for x, y in generateScaledSegment(segment, height, scale):
|
||||
fp.write(u' {} {}'.format(x, y))
|
||||
fp.write(u' Z" style="fill:none;stroke:black"/>\n')
|
||||
fp.write(u'</g>\n')
|
||||
|
||||
# Draw all un-closed paths
|
||||
if len(straightSegments) > 0:
|
||||
fp.write(u'<g>\n')
|
||||
for segment in straightSegments:
|
||||
fp.write(u'<path d="M')
|
||||
for x, y in generateScaledSegment(segment, height, scale):
|
||||
fp.write(u' {} {}'.format(x, y))
|
||||
fp.write(u'" style="fill:none;stroke:black"/>\n')
|
||||
fp.write(u'</g>\n')
|
||||
|
||||
# Close the XML
|
||||
fp.write(u'</svg>\n')
|
||||
|
||||
# Close the file if necessary
|
||||
if fp != sys.stdout:
|
||||
fp.close()
|
||||
|
||||
def main():
|
||||
# Setup the command line argument parser
|
||||
cmdArgParser = argparse.ArgumentParser(
|
||||
description = u'Convert GPX formatted geodata to Scalable Vector Graphics (SVG)',
|
||||
epilog = u'gpx2svg {} - http://nasauber.de/opensource/gpx2svg/'.format(__version__)
|
||||
)
|
||||
cmdArgParser.add_argument(
|
||||
u'i', metavar = u'FILE', nargs = u'?', default = u'/dev/stdin',
|
||||
help = u'GPX input file (default: read from STDIN)'
|
||||
)
|
||||
cmdArgParser.add_argument(
|
||||
u'--o', metavar = u'FILE', nargs = u'?', default = u'/dev/stdout',
|
||||
help = u'SVG output file (default: write to STDOUT)'
|
||||
)
|
||||
cmdArgParser.add_argument(
|
||||
u'--m', metavar = u'PIXELS', nargs = u'?', type = int, default = 3000,
|
||||
help = u'Maximum width or height of the SVG output in pixels (default: 3000)'
|
||||
)
|
||||
cmdArgParser.add_argument(
|
||||
u'--d',
|
||||
help = u'Drop single points (default: draw a circle with 1px diameter)'
|
||||
)
|
||||
cmdArgParser.add_argument(
|
||||
u'--r',
|
||||
help = (u'"Raw" conversion: Create one SVG path per track segment, don\'t try to combine '
|
||||
u'paths that end with the starting point of another path')
|
||||
)
|
||||
cmdArgParser.add_argument(
|
||||
u'--j',
|
||||
help = (u'Join all segments to a big one in the order of the GPX file. This can create an '
|
||||
u'un-scattered path if the default combining algorithm does not work because there '
|
||||
u'are no matching points across segments (implies -r)')
|
||||
)
|
||||
cmdArgParser.add_argument(
|
||||
u'--tab',
|
||||
help = (u'inkscape option')
|
||||
)
|
||||
|
||||
|
||||
# Get the given arguments
|
||||
cmdArgs = cmdArgParser.parse_args()
|
||||
|
||||
# Map "-" to STDIN or STDOUT
|
||||
if cmdArgs.i == u'-':
|
||||
cmdArgs.i = u'/dev/stdin'
|
||||
if cmdArgs.o == u'-':
|
||||
cmdArgs.o = u'/dev/stdout'
|
||||
|
||||
# Check if a given input or output file name is a relative representation of STDIN or STDOUT
|
||||
if cmdArgs.i != u'/dev/stdin':
|
||||
if abspath(cmdArgs.i) == u'/dev/stdin':
|
||||
cmdArgs.i = u'/dev/stdin'
|
||||
if cmdArgs.o != u'/dev/stdout':
|
||||
if abspath(cmdArgs.o) == u'/dev/stdout':
|
||||
cmdArgs.o = u'/dev/stdout'
|
||||
|
||||
# Get the latitude and longitude data from the given GPX file or STDIN
|
||||
gpsData = parseGpx(cmdArgs.i)
|
||||
|
||||
# Check if we actually _have_ data
|
||||
if gpsData == []:
|
||||
print (sys.stderr, u'No data to convert. Terminating.')
|
||||
sys.exit(1)
|
||||
|
||||
# Join all segments if requested by "-j"
|
||||
if bool(cmdArgs.j):
|
||||
gpsData = chronologyJoinSegments(gpsData)
|
||||
|
||||
# Try to combine all track segments that can be combined if not requested otherwise
|
||||
# Don't execute if all segments are already joined with "-j"
|
||||
if not bool(cmdArgs.r) and not bool(cmdArgs.j):
|
||||
gpsData = combineSegments(gpsData)
|
||||
|
||||
# Calculate a plane projection for a GPS dataset
|
||||
# At the moment, we only have the Mercator projection
|
||||
gpsData = calcProjection(gpsData)
|
||||
|
||||
# Move the projected data to the 0,0 origin of a cartesial coordinate system
|
||||
# and get the raw width and height of the resulting vector data
|
||||
gpsData, width, height = moveProjectedData(gpsData)
|
||||
|
||||
# Write the resulting SVG data to the requested output file or STDOUT
|
||||
writeSvgData(gpsData, width, height, cmdArgs.m, bool(cmdArgs.d), cmdArgs.o)
|
||||
|
||||
if __name__ == u'__main__':
|
||||
main()
|
21
extensions/fablabchemnitz/gpx_import/meta.json
Normal file
21
extensions/fablabchemnitz/gpx_import/meta.json
Normal file
@ -0,0 +1,21 @@
|
||||
[
|
||||
{
|
||||
"name": "GPX Import",
|
||||
"id": "fablabchemnitz.de.gpx_import",
|
||||
"path": "gpx_import",
|
||||
"dependent_extensions": null,
|
||||
"original_name": "GPX Import",
|
||||
"original_id": "mono.inkscape.pgx_input",
|
||||
"license": "GNU GPL v2",
|
||||
"license_url": "https://inkscape.org/de/~mono/%E2%98%85inkgpx2svg",
|
||||
"comment": "",
|
||||
"source_url": "https://gitea.fablabchemnitz.de/FabLab_Chemnitz/mightyscape-1.2/src/branch/master/extensions/fablabchemnitz/gpx_import",
|
||||
"fork_url": "https://git.disroot.org/monomono/inkgpx2svg",
|
||||
"documentation_url": "https://stadtfabrikanten.org/display/IFM/GPX+Import",
|
||||
"inkscape_gallery_url": null,
|
||||
"main_authors": [
|
||||
"inkscape.org/mono",
|
||||
"github.com/eridur-de"
|
||||
]
|
||||
}
|
||||
]
|
667
extensions/fablabchemnitz/gradient_saver/GUI.glade
Normal file
667
extensions/fablabchemnitz/gradient_saver/GUI.glade
Normal file
@ -0,0 +1,667 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<!-- Generated with glade 3.22.1 -->
|
||||
<interface>
|
||||
<requires lib="gtk+" version="3.20"/>
|
||||
<object class="GtkWindow" id="window">
|
||||
<property name="can_focus">False</property>
|
||||
<property name="title" translatable="yes">Gradient Saver</property>
|
||||
<property name="resizable">False</property>
|
||||
<property name="window_position">center</property>
|
||||
<property name="default_width">600</property>
|
||||
<property name="default_height">400</property>
|
||||
<property name="icon">icon.svg</property>
|
||||
<property name="gravity">north</property>
|
||||
<signal name="destroy" handler="onDestroy" swapped="no"/>
|
||||
<child>
|
||||
<placeholder/>
|
||||
</child>
|
||||
<child>
|
||||
<object class="GtkNotebook" id="active_page">
|
||||
<property name="visible">True</property>
|
||||
<property name="can_focus">True</property>
|
||||
<signal name="switch-page" handler="onSwitchPage" swapped="no"/>
|
||||
<child>
|
||||
<object class="GtkLayout">
|
||||
<property name="visible">True</property>
|
||||
<property name="can_focus">False</property>
|
||||
<property name="width">400</property>
|
||||
<property name="height">250</property>
|
||||
<child>
|
||||
<object class="GtkScrolledWindow">
|
||||
<property name="width_request">600</property>
|
||||
<property name="height_request">180</property>
|
||||
<property name="visible">True</property>
|
||||
<property name="can_focus">True</property>
|
||||
<child>
|
||||
<object class="GtkViewport">
|
||||
<property name="visible">True</property>
|
||||
<property name="can_focus">False</property>
|
||||
<property name="shadow_type">none</property>
|
||||
<child>
|
||||
<object class="GtkBox" id="save_gradients_container">
|
||||
<property name="visible">True</property>
|
||||
<property name="can_focus">False</property>
|
||||
<property name="margin_left">30</property>
|
||||
<property name="margin_top">10</property>
|
||||
<property name="border_width">2</property>
|
||||
<property name="orientation">vertical</property>
|
||||
<property name="spacing">20</property>
|
||||
<child>
|
||||
<object class="GtkBox" id="save_gradient1">
|
||||
<property name="visible">True</property>
|
||||
<property name="can_focus">False</property>
|
||||
<property name="margin_top">10</property>
|
||||
<property name="spacing">18</property>
|
||||
<child>
|
||||
<object class="GtkDrawingArea" id="save_gradient_draw">
|
||||
<property name="width_request">150</property>
|
||||
<property name="height_request">42</property>
|
||||
<property name="visible">True</property>
|
||||
<property name="app_paintable">True</property>
|
||||
<property name="can_focus">False</property>
|
||||
</object>
|
||||
<packing>
|
||||
<property name="expand">False</property>
|
||||
<property name="fill">True</property>
|
||||
<property name="position">0</property>
|
||||
</packing>
|
||||
</child>
|
||||
<child>
|
||||
<object class="GtkEntry" id="save_gradient_name">
|
||||
<property name="width_request">325</property>
|
||||
<property name="height_request">42</property>
|
||||
<property name="visible">True</property>
|
||||
<property name="can_focus">True</property>
|
||||
<property name="max_length">25</property>
|
||||
<property name="placeholder_text" translatable="yes">e.g Beautiful Color</property>
|
||||
</object>
|
||||
<packing>
|
||||
<property name="expand">False</property>
|
||||
<property name="fill">True</property>
|
||||
<property name="position">1</property>
|
||||
</packing>
|
||||
</child>
|
||||
</object>
|
||||
<packing>
|
||||
<property name="expand">False</property>
|
||||
<property name="fill">False</property>
|
||||
<property name="position">1</property>
|
||||
</packing>
|
||||
</child>
|
||||
</object>
|
||||
</child>
|
||||
</object>
|
||||
</child>
|
||||
</object>
|
||||
<packing>
|
||||
<property name="y">130</property>
|
||||
</packing>
|
||||
</child>
|
||||
<child>
|
||||
<object class="GtkButtonBox">
|
||||
<property name="width_request">580</property>
|
||||
<property name="height_request">32</property>
|
||||
<property name="visible">True</property>
|
||||
<property name="can_focus">False</property>
|
||||
<property name="margin_right">20</property>
|
||||
<property name="spacing">10</property>
|
||||
<property name="layout_style">end</property>
|
||||
<child>
|
||||
<object class="GtkButton" id="save_btn_cancel">
|
||||
<property name="label" translatable="yes">Cancel</property>
|
||||
<property name="visible">True</property>
|
||||
<property name="can_focus">True</property>
|
||||
<property name="receives_default">True</property>
|
||||
<signal name="clicked" handler="onDestroy" swapped="no"/>
|
||||
</object>
|
||||
<packing>
|
||||
<property name="expand">True</property>
|
||||
<property name="fill">True</property>
|
||||
<property name="position">0</property>
|
||||
</packing>
|
||||
</child>
|
||||
<child>
|
||||
<object class="GtkButton" id="save_btn_apply">
|
||||
<property name="label" translatable="yes">Save</property>
|
||||
<property name="visible">True</property>
|
||||
<property name="can_focus">True</property>
|
||||
<property name="receives_default">True</property>
|
||||
<signal name="clicked" handler="onSaveGradientClicked" swapped="no"/>
|
||||
</object>
|
||||
<packing>
|
||||
<property name="expand">True</property>
|
||||
<property name="fill">True</property>
|
||||
<property name="position">1</property>
|
||||
</packing>
|
||||
</child>
|
||||
</object>
|
||||
<packing>
|
||||
<property name="y">318</property>
|
||||
</packing>
|
||||
</child>
|
||||
<child>
|
||||
<object class="GtkBox">
|
||||
<property name="width_request">600</property>
|
||||
<property name="height_request">100</property>
|
||||
<property name="visible">True</property>
|
||||
<property name="can_focus">False</property>
|
||||
<property name="margin_bottom">10</property>
|
||||
<property name="baseline_position">top</property>
|
||||
<child>
|
||||
<object class="GtkImage">
|
||||
<property name="width_request">55</property>
|
||||
<property name="visible">True</property>
|
||||
<property name="can_focus">False</property>
|
||||
<property name="margin_left">30</property>
|
||||
<property name="margin_top">21</property>
|
||||
<property name="stock">gtk-info</property>
|
||||
<property name="icon_size">6</property>
|
||||
</object>
|
||||
<packing>
|
||||
<property name="expand">False</property>
|
||||
<property name="fill">True</property>
|
||||
<property name="position">0</property>
|
||||
</packing>
|
||||
</child>
|
||||
<child>
|
||||
<object class="GtkLabel">
|
||||
<property name="width_request">250</property>
|
||||
<property name="visible">True</property>
|
||||
<property name="can_focus">False</property>
|
||||
<property name="margin_right">30</property>
|
||||
<property name="margin_top">14</property>
|
||||
<property name="label" translatable="yes"><b>Hint:</b>
|
||||
Select at least one object that use gradient color in order to add those gradient to your library. Selected gradient object will appear below. You can give a name for your gradients to help you recognize it later.</property>
|
||||
<property name="use_markup">True</property>
|
||||
<property name="wrap">True</property>
|
||||
</object>
|
||||
<packing>
|
||||
<property name="expand">False</property>
|
||||
<property name="fill">True</property>
|
||||
<property name="position">1</property>
|
||||
</packing>
|
||||
</child>
|
||||
</object>
|
||||
</child>
|
||||
<child>
|
||||
<object class="GtkBox">
|
||||
<property name="width_request">550</property>
|
||||
<property name="height_request">20</property>
|
||||
<property name="visible">True</property>
|
||||
<property name="can_focus">False</property>
|
||||
<property name="margin_left">45</property>
|
||||
<property name="margin_right">50</property>
|
||||
<property name="margin_bottom">10</property>
|
||||
<property name="spacing">100</property>
|
||||
<child>
|
||||
<object class="GtkLabel">
|
||||
<property name="visible">True</property>
|
||||
<property name="can_focus">False</property>
|
||||
<property name="label" translatable="yes"><b>Preview</b></property>
|
||||
<property name="use_markup">True</property>
|
||||
</object>
|
||||
<packing>
|
||||
<property name="expand">False</property>
|
||||
<property name="fill">True</property>
|
||||
<property name="position">0</property>
|
||||
</packing>
|
||||
</child>
|
||||
<child>
|
||||
<object class="GtkLabel">
|
||||
<property name="visible">True</property>
|
||||
<property name="can_focus">False</property>
|
||||
<property name="label" translatable="yes"><b>Gradient Name</b></property>
|
||||
<property name="use_markup">True</property>
|
||||
</object>
|
||||
<packing>
|
||||
<property name="expand">False</property>
|
||||
<property name="fill">True</property>
|
||||
<property name="position">1</property>
|
||||
</packing>
|
||||
</child>
|
||||
</object>
|
||||
<packing>
|
||||
<property name="y">100</property>
|
||||
</packing>
|
||||
</child>
|
||||
</object>
|
||||
</child>
|
||||
<child type="tab">
|
||||
<object class="GtkLabel">
|
||||
<property name="visible">True</property>
|
||||
<property name="can_focus">False</property>
|
||||
<property name="label" translatable="yes">Add New</property>
|
||||
</object>
|
||||
<packing>
|
||||
<property name="tab_fill">False</property>
|
||||
</packing>
|
||||
</child>
|
||||
<child>
|
||||
<object class="GtkLayout">
|
||||
<property name="visible">True</property>
|
||||
<property name="can_focus">False</property>
|
||||
<child>
|
||||
<object class="GtkButtonBox">
|
||||
<property name="width_request">580</property>
|
||||
<property name="height_request">32</property>
|
||||
<property name="visible">True</property>
|
||||
<property name="can_focus">False</property>
|
||||
<property name="margin_right">20</property>
|
||||
<property name="spacing">6</property>
|
||||
<property name="baseline_position">bottom</property>
|
||||
<property name="layout_style">end</property>
|
||||
<child>
|
||||
<object class="GtkButton" id="load_gradient_remove1">
|
||||
<property name="label" translatable="yes">Remove</property>
|
||||
<property name="visible">True</property>
|
||||
<property name="can_focus">True</property>
|
||||
<property name="receives_default">True</property>
|
||||
<property name="always_show_image">True</property>
|
||||
<signal name="clicked" handler="onRemoveGradientClicked" swapped="no"/>
|
||||
</object>
|
||||
<packing>
|
||||
<property name="expand">True</property>
|
||||
<property name="fill">True</property>
|
||||
<property name="position">0</property>
|
||||
</packing>
|
||||
</child>
|
||||
<child>
|
||||
<object class="GtkButton" id="load_gradient_add1">
|
||||
<property name="label" translatable="yes">Load</property>
|
||||
<property name="visible">True</property>
|
||||
<property name="can_focus">True</property>
|
||||
<property name="receives_default">True</property>
|
||||
<property name="always_show_image">True</property>
|
||||
<signal name="clicked" handler="onLoadGradientClicked" swapped="no"/>
|
||||
</object>
|
||||
<packing>
|
||||
<property name="expand">True</property>
|
||||
<property name="fill">True</property>
|
||||
<property name="position">1</property>
|
||||
</packing>
|
||||
</child>
|
||||
</object>
|
||||
<packing>
|
||||
<property name="y">318</property>
|
||||
</packing>
|
||||
</child>
|
||||
<child>
|
||||
<object class="GtkBox">
|
||||
<property name="width_request">600</property>
|
||||
<property name="height_request">100</property>
|
||||
<property name="visible">True</property>
|
||||
<property name="can_focus">False</property>
|
||||
<property name="margin_bottom">10</property>
|
||||
<property name="baseline_position">top</property>
|
||||
<child>
|
||||
<object class="GtkImage">
|
||||
<property name="width_request">55</property>
|
||||
<property name="visible">True</property>
|
||||
<property name="can_focus">False</property>
|
||||
<property name="margin_left">30</property>
|
||||
<property name="margin_top">21</property>
|
||||
<property name="stock">gtk-info</property>
|
||||
<property name="icon_size">6</property>
|
||||
</object>
|
||||
<packing>
|
||||
<property name="expand">False</property>
|
||||
<property name="fill">True</property>
|
||||
<property name="position">0</property>
|
||||
</packing>
|
||||
</child>
|
||||
<child>
|
||||
<object class="GtkLabel">
|
||||
<property name="width_request">250</property>
|
||||
<property name="visible">True</property>
|
||||
<property name="can_focus">False</property>
|
||||
<property name="margin_right">30</property>
|
||||
<property name="margin_top">14</property>
|
||||
<property name="label" translatable="yes"><b>Hint:</b>
|
||||
Select at least one object that use gradient color in order to add those gradient to your library. Selected gradient object will appear below. You can give a name for your gradients to help you recognize it later.</property>
|
||||
<property name="use_markup">True</property>
|
||||
<property name="wrap">True</property>
|
||||
</object>
|
||||
<packing>
|
||||
<property name="expand">False</property>
|
||||
<property name="fill">True</property>
|
||||
<property name="position">1</property>
|
||||
</packing>
|
||||
</child>
|
||||
</object>
|
||||
</child>
|
||||
<child>
|
||||
<object class="GtkBox">
|
||||
<property name="width_request">550</property>
|
||||
<property name="height_request">20</property>
|
||||
<property name="visible">True</property>
|
||||
<property name="can_focus">False</property>
|
||||
<property name="margin_left">45</property>
|
||||
<property name="margin_right">50</property>
|
||||
<property name="margin_bottom">10</property>
|
||||
<property name="spacing">100</property>
|
||||
<child>
|
||||
<object class="GtkLabel">
|
||||
<property name="visible">True</property>
|
||||
<property name="can_focus">False</property>
|
||||
<property name="label" translatable="yes"><b>Your Current Gradient</b></property>
|
||||
<property name="use_markup">True</property>
|
||||
</object>
|
||||
<packing>
|
||||
<property name="expand">False</property>
|
||||
<property name="fill">True</property>
|
||||
<property name="position">0</property>
|
||||
</packing>
|
||||
</child>
|
||||
</object>
|
||||
<packing>
|
||||
<property name="y">100</property>
|
||||
</packing>
|
||||
</child>
|
||||
<child>
|
||||
<object class="GtkScrolledWindow">
|
||||
<property name="width_request">600</property>
|
||||
<property name="height_request">180</property>
|
||||
<property name="visible">True</property>
|
||||
<property name="can_focus">True</property>
|
||||
<child>
|
||||
<object class="GtkViewport">
|
||||
<property name="visible">True</property>
|
||||
<property name="can_focus">False</property>
|
||||
<property name="shadow_type">none</property>
|
||||
<child>
|
||||
<object class="GtkFlowBox" id="load_gradients_container">
|
||||
<property name="visible">True</property>
|
||||
<property name="can_focus">False</property>
|
||||
<property name="valign">start</property>
|
||||
<property name="margin_left">10</property>
|
||||
<property name="margin_right">10</property>
|
||||
<property name="column_spacing">30</property>
|
||||
<property name="row_spacing">10</property>
|
||||
<property name="min_children_per_line">2</property>
|
||||
<property name="max_children_per_line">2</property>
|
||||
<property name="selection_mode">none</property>
|
||||
<property name="activate_on_single_click">False</property>
|
||||
<child>
|
||||
<object class="GtkFlowBoxChild" id="load_gradient1">
|
||||
<property name="width_request">60</property>
|
||||
<property name="height_request">42</property>
|
||||
<property name="visible">True</property>
|
||||
<property name="can_focus">True</property>
|
||||
<property name="halign">start</property>
|
||||
<property name="valign">start</property>
|
||||
<child>
|
||||
<object class="GtkBox">
|
||||
<property name="visible">True</property>
|
||||
<property name="can_focus">False</property>
|
||||
<property name="spacing">5</property>
|
||||
<property name="baseline_position">top</property>
|
||||
<child>
|
||||
<object class="GtkCheckButton" id="load_gradient_select">
|
||||
<property name="height_request">42</property>
|
||||
<property name="visible">True</property>
|
||||
<property name="can_focus">True</property>
|
||||
<property name="receives_default">False</property>
|
||||
<property name="draw_indicator">True</property>
|
||||
</object>
|
||||
<packing>
|
||||
<property name="expand">False</property>
|
||||
<property name="fill">True</property>
|
||||
<property name="position">0</property>
|
||||
</packing>
|
||||
</child>
|
||||
<child>
|
||||
<object class="GtkDrawingArea" id="load_gradient_draw">
|
||||
<property name="width_request">100</property>
|
||||
<property name="height_request">42</property>
|
||||
<property name="visible">True</property>
|
||||
<property name="app_paintable">True</property>
|
||||
<property name="can_focus">False</property>
|
||||
</object>
|
||||
<packing>
|
||||
<property name="expand">False</property>
|
||||
<property name="fill">True</property>
|
||||
<property name="position">1</property>
|
||||
</packing>
|
||||
</child>
|
||||
<child>
|
||||
<object class="GtkLabel" id="load_gradient_text">
|
||||
<property name="height_request">42</property>
|
||||
<property name="visible">True</property>
|
||||
<property name="can_focus">False</property>
|
||||
<property name="label" translatable="yes">ijo trans</property>
|
||||
<property name="wrap">True</property>
|
||||
<property name="wrap_mode">char</property>
|
||||
<property name="max_width_chars">25</property>
|
||||
</object>
|
||||
<packing>
|
||||
<property name="expand">False</property>
|
||||
<property name="fill">True</property>
|
||||
<property name="position">2</property>
|
||||
</packing>
|
||||
</child>
|
||||
</object>
|
||||
</child>
|
||||
</object>
|
||||
</child>
|
||||
</object>
|
||||
</child>
|
||||
</object>
|
||||
</child>
|
||||
</object>
|
||||
<packing>
|
||||
<property name="y">130</property>
|
||||
</packing>
|
||||
</child>
|
||||
</object>
|
||||
<packing>
|
||||
<property name="position">1</property>
|
||||
</packing>
|
||||
</child>
|
||||
<child type="tab">
|
||||
<object class="GtkLabel">
|
||||
<property name="visible">True</property>
|
||||
<property name="can_focus">False</property>
|
||||
<property name="label" translatable="yes">Load or Remove</property>
|
||||
</object>
|
||||
<packing>
|
||||
<property name="position">1</property>
|
||||
<property name="tab_fill">False</property>
|
||||
</packing>
|
||||
</child>
|
||||
<child>
|
||||
<object class="GtkLayout">
|
||||
<property name="visible">True</property>
|
||||
<property name="can_focus">False</property>
|
||||
<child>
|
||||
<object class="GtkLabel" id="extension_version">
|
||||
<property name="width_request">317</property>
|
||||
<property name="height_request">300</property>
|
||||
<property name="visible">True</property>
|
||||
<property name="can_focus">False</property>
|
||||
<property name="label" translatable="yes"><span font="12"><b>Version $VERSION</b></span></property>
|
||||
<property name="use_markup">True</property>
|
||||
<property name="wrap">True</property>
|
||||
</object>
|
||||
<packing>
|
||||
<property name="x">137</property>
|
||||
<property name="y">-84</property>
|
||||
</packing>
|
||||
</child>
|
||||
<child>
|
||||
<object class="GtkImage">
|
||||
<property name="width_request">100</property>
|
||||
<property name="height_request">80</property>
|
||||
<property name="visible">True</property>
|
||||
<property name="can_focus">False</property>
|
||||
<property name="pixbuf">icon.svg</property>
|
||||
</object>
|
||||
<packing>
|
||||
<property name="x">10</property>
|
||||
<property name="y">32</property>
|
||||
</packing>
|
||||
</child>
|
||||
<child>
|
||||
<object class="GtkLabel">
|
||||
<property name="width_request">100</property>
|
||||
<property name="height_request">80</property>
|
||||
<property name="visible">True</property>
|
||||
<property name="can_focus">False</property>
|
||||
<property name="label" translatable="yes"><span font="12"><b>Gradient Saver</b></span></property>
|
||||
<property name="use_markup">True</property>
|
||||
</object>
|
||||
<packing>
|
||||
<property name="x">69</property>
|
||||
<property name="y">225</property>
|
||||
</packing>
|
||||
</child>
|
||||
<child>
|
||||
<object class="GtkLabel">
|
||||
<property name="width_request">307</property>
|
||||
<property name="height_request">80</property>
|
||||
<property name="visible">True</property>
|
||||
<property name="can_focus">False</property>
|
||||
<property name="label" translatable="yes"><span>Gradient Saver is an extension for Inkscape that will help you to organize your favorite gradients. This extension created with love by <a href="#">Sofyan</a> &amp; <a href="https://raniaamina.id">Rania Amina</a> and fully supported by Gimpscape ID Community.
|
||||
|
||||
Project Repository:
|
||||
<a href="#"><b>https://github.com/artemtech/inkscape-gradient-saver</b></a></span></property>
|
||||
<property name="use_markup">True</property>
|
||||
<property name="wrap">True</property>
|
||||
</object>
|
||||
<packing>
|
||||
<property name="x">243</property>
|
||||
<property name="y">82</property>
|
||||
</packing>
|
||||
</child>
|
||||
<child>
|
||||
<object class="GtkButtonBox">
|
||||
<property name="width_request">580</property>
|
||||
<property name="height_request">32</property>
|
||||
<property name="visible">True</property>
|
||||
<property name="can_focus">False</property>
|
||||
<property name="margin_right">20</property>
|
||||
<property name="spacing">10</property>
|
||||
<property name="layout_style">end</property>
|
||||
<child>
|
||||
<object class="GtkButton" id="about_btn_close">
|
||||
<property name="label" translatable="yes">Close</property>
|
||||
<property name="visible">True</property>
|
||||
<property name="can_focus">True</property>
|
||||
<property name="receives_default">True</property>
|
||||
<signal name="clicked" handler="onDestroy" swapped="no"/>
|
||||
</object>
|
||||
<packing>
|
||||
<property name="expand">True</property>
|
||||
<property name="fill">True</property>
|
||||
<property name="position">1</property>
|
||||
</packing>
|
||||
</child>
|
||||
</object>
|
||||
<packing>
|
||||
<property name="y">318</property>
|
||||
</packing>
|
||||
</child>
|
||||
</object>
|
||||
<packing>
|
||||
<property name="position">2</property>
|
||||
</packing>
|
||||
</child>
|
||||
<child type="tab">
|
||||
<object class="GtkLabel">
|
||||
<property name="visible">True</property>
|
||||
<property name="can_focus">False</property>
|
||||
<property name="label" translatable="yes">About</property>
|
||||
</object>
|
||||
<packing>
|
||||
<property name="position">2</property>
|
||||
<property name="tab_fill">False</property>
|
||||
</packing>
|
||||
</child>
|
||||
</object>
|
||||
</child>
|
||||
</object>
|
||||
<object class="GtkDialog" id="information_dialog">
|
||||
<property name="can_focus">False</property>
|
||||
<property name="title" translatable="yes">Information</property>
|
||||
<property name="icon_name">dialog-information</property>
|
||||
<property name="type_hint">dialog</property>
|
||||
<property name="attached_to">window</property>
|
||||
<child>
|
||||
<placeholder/>
|
||||
</child>
|
||||
<child internal-child="vbox">
|
||||
<object class="GtkBox">
|
||||
<property name="can_focus">False</property>
|
||||
<property name="margin_left">10</property>
|
||||
<property name="margin_right">10</property>
|
||||
<property name="margin_top">10</property>
|
||||
<property name="margin_bottom">10</property>
|
||||
<property name="orientation">vertical</property>
|
||||
<property name="spacing">2</property>
|
||||
<child internal-child="action_area">
|
||||
<object class="GtkButtonBox">
|
||||
<property name="can_focus">False</property>
|
||||
<property name="margin_top">10</property>
|
||||
<property name="margin_bottom">10</property>
|
||||
<property name="layout_style">center</property>
|
||||
<child>
|
||||
<object class="GtkButton" id="information_button">
|
||||
<property name="label" translatable="yes">Close</property>
|
||||
<property name="visible">True</property>
|
||||
<property name="can_focus">True</property>
|
||||
<property name="receives_default">True</property>
|
||||
<signal name="clicked" handler="onDestroy" swapped="no"/>
|
||||
</object>
|
||||
<packing>
|
||||
<property name="expand">True</property>
|
||||
<property name="fill">True</property>
|
||||
<property name="position">0</property>
|
||||
</packing>
|
||||
</child>
|
||||
</object>
|
||||
<packing>
|
||||
<property name="expand">False</property>
|
||||
<property name="fill">False</property>
|
||||
<property name="position">0</property>
|
||||
</packing>
|
||||
</child>
|
||||
<child>
|
||||
<object class="GtkBox">
|
||||
<property name="visible">True</property>
|
||||
<property name="can_focus">False</property>
|
||||
<child>
|
||||
<object class="GtkImage">
|
||||
<property name="width_request">55</property>
|
||||
<property name="visible">True</property>
|
||||
<property name="can_focus">False</property>
|
||||
<property name="stock">gtk-info</property>
|
||||
<property name="icon_size">6</property>
|
||||
</object>
|
||||
<packing>
|
||||
<property name="expand">False</property>
|
||||
<property name="fill">True</property>
|
||||
<property name="position">0</property>
|
||||
</packing>
|
||||
</child>
|
||||
<child>
|
||||
<object class="GtkLabel" id="information_text">
|
||||
<property name="visible">True</property>
|
||||
<property name="can_focus">False</property>
|
||||
<property name="label" translatable="yes">label</property>
|
||||
</object>
|
||||
<packing>
|
||||
<property name="expand">False</property>
|
||||
<property name="fill">True</property>
|
||||
<property name="position">1</property>
|
||||
</packing>
|
||||
</child>
|
||||
</object>
|
||||
<packing>
|
||||
<property name="expand">False</property>
|
||||
<property name="fill">True</property>
|
||||
<property name="position">1</property>
|
||||
</packing>
|
||||
</child>
|
||||
</object>
|
||||
</child>
|
||||
</object>
|
||||
</interface>
|
16
extensions/fablabchemnitz/gradient_saver/gradient_saver.inx
Normal file
16
extensions/fablabchemnitz/gradient_saver/gradient_saver.inx
Normal file
@ -0,0 +1,16 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<inkscape-extension xmlns="http://www.inkscape.org/namespace/inkscape/extension">
|
||||
<name>Gradient Saver</name>
|
||||
<id>fablabchemnitz.de.gradient_saver</id>
|
||||
<effect>
|
||||
<object-type>all</object-type>
|
||||
<effects-menu>
|
||||
<submenu name="FabLab Chemnitz">
|
||||
<submenu name="Colors/Gradients/Filters"/>
|
||||
</submenu>
|
||||
</effects-menu>
|
||||
</effect>
|
||||
<script>
|
||||
<command location="inx" interpreter="python">gradient_saver.py</command>
|
||||
</script>
|
||||
</inkscape-extension>
|
386
extensions/fablabchemnitz/gradient_saver/gradient_saver.py
Normal file
386
extensions/fablabchemnitz/gradient_saver/gradient_saver.py
Normal file
@ -0,0 +1,386 @@
|
||||
#! /usr/bin/env python3
|
||||
|
||||
# OS modules
|
||||
import os
|
||||
import sys
|
||||
|
||||
import gi
|
||||
gi.require_version("Gtk", "3.0")
|
||||
from gi.repository import Gtk
|
||||
|
||||
# inkscape extension files
|
||||
import cairo
|
||||
from lxml import etree
|
||||
import inkex # required
|
||||
from inkex.elements import NSS
|
||||
from inkex.utils import errormsg as show_errormsg
|
||||
from inkex.styles import Style
|
||||
from inkex.colors import Color
|
||||
|
||||
__version__ = '1.0.0'
|
||||
|
||||
saved_gradient_path = "../my-gradients.svg"
|
||||
|
||||
def create_new_file(gradient_data):
|
||||
root = etree.Element("svg", nsmap=NSS)
|
||||
def_tree = etree.SubElement(root, "defs")
|
||||
for i, item in enumerate(gradient_data):
|
||||
gradient = etree.SubElement(def_tree, item.tag, attrib=item.attrib)
|
||||
for j, gradient_stop in enumerate(item):
|
||||
etree.SubElement(gradient, gradient_stop.tag, attrib=gradient_stop.attrib, id="stop%d%d" % (i, j))
|
||||
with open(saved_gradient_path, "w") as f:
|
||||
f.write(etree.tostring(
|
||||
root, encoding="utf-8", xml_declaration=True, pretty_print=True).decode("utf-8"))
|
||||
|
||||
def save_to_file(data):
|
||||
""" Wrapper for saving gradients to file. """
|
||||
if len(data) == 0:
|
||||
return 1
|
||||
else:
|
||||
try:
|
||||
# read previous data then append it with current data
|
||||
if os.path.exists(saved_gradient_path):
|
||||
previous_data = load_gradients_from_file()
|
||||
data = previous_data + data
|
||||
create_new_file(data)
|
||||
return 0
|
||||
except Exception as e:
|
||||
import traceback
|
||||
show_errormsg(e)
|
||||
show_errormsg(traceback.print_exc())
|
||||
return -1
|
||||
|
||||
def load_gradients_from_file():
|
||||
""" Load gradients from saved gradient, returned as List """
|
||||
if os.path.exists(saved_gradient_path) and os.stat(saved_gradient_path).st_size != 0:
|
||||
root = etree.parse(saved_gradient_path)
|
||||
mygradients = root.xpath("//linearGradient", namespaces=NSS)
|
||||
else:
|
||||
mygradients = []
|
||||
return mygradients
|
||||
|
||||
def read_stop_gradient(gradient):
|
||||
stop_data = {
|
||||
"id": gradient.attrib.get("id"),
|
||||
"stops": []
|
||||
}
|
||||
for stop in gradient:
|
||||
offset = stop.attrib.get("offset")
|
||||
style = Style(Style.parse_str(stop.attrib['style']))
|
||||
color = Color.parse_str(style.get("stop-color"))[1]
|
||||
opacity = style.get("stop-opacity")
|
||||
stop_data.get("stops").append(
|
||||
tuple([float(offset)] + [x/256.0 for x in color] + [float(opacity)]))
|
||||
return stop_data
|
||||
|
||||
class MainWindow(Gtk.Builder):
|
||||
def __init__(self, gradientSaver):
|
||||
Gtk.Builder.__init__(self)
|
||||
self.gradientSaver = gradientSaver
|
||||
self.add_from_file("GUI.glade")
|
||||
self.window = self.get_object("window")
|
||||
self.app_version = self.get_object("extension_version")
|
||||
self.app_version.set_label(self.app_version.get_label().replace("$VERSION",__version__))
|
||||
self.information_dialog = self.get_object("information_dialog")
|
||||
# parsing components
|
||||
# save gradient components
|
||||
self.save_container = self.get_object("save_gradients_container")
|
||||
save_template = self.get_object("save_gradient1")
|
||||
self.save_container.remove(save_template)
|
||||
for idx, item in enumerate(self.gradientSaver.doc_selected_gradients):
|
||||
new_save_template = self.SaveGradientTemplate(item)
|
||||
new_save_template.set_name("gradient%d" % idx)
|
||||
self.save_container.add(new_save_template)
|
||||
self.save_container.show_all()
|
||||
# - end save gradient components
|
||||
# load gradient components
|
||||
self.load_container = self.get_object("load_gradients_container")
|
||||
load_template = self.get_object("load_gradient1")
|
||||
self.load_container.remove(load_template)
|
||||
# - end load gradient components
|
||||
# show the GUI
|
||||
self.connect_signals(self.Handler(self))
|
||||
self.window.show()
|
||||
|
||||
class SaveGradientTemplate(Gtk.HBox):
|
||||
"""
|
||||
Template for generating gradient name
|
||||
and preview of selected object in the save page.
|
||||
"""
|
||||
|
||||
def __init__(self, gradient_data):
|
||||
Gtk.HBox.__init__(self)
|
||||
self.gradient_data = gradient_data
|
||||
self.set_spacing(20)
|
||||
preview = Gtk.DrawingArea()
|
||||
preview.set_size_request(150, 42)
|
||||
preview.set_app_paintable(True)
|
||||
preview.connect("draw", self.on_draw, gradient_data)
|
||||
self.pack_start(preview, False, True, 0)
|
||||
self.input_entry = Gtk.Entry()
|
||||
self.input_entry.set_placeholder_text("e.g Beautiful Color")
|
||||
self.input_entry.set_size_request(250, 42)
|
||||
self.input_entry.set_text(gradient_data.get("id"))
|
||||
self.input_entry.set_max_length(25)
|
||||
self.pack_start(self.input_entry, False, True, 1)
|
||||
|
||||
def on_draw(self, wid, cr, data):
|
||||
"""
|
||||
Calllback for draw signal for rendering gradient.
|
||||
params:
|
||||
- wid :GtkWidget
|
||||
- cr :Cairo
|
||||
- data :list -> gradient data
|
||||
"""
|
||||
lg = cairo.LinearGradient(0.0, 20.0, 150.0, 20.0)
|
||||
for stop in data["stops"]:
|
||||
lg.add_color_stop_rgba(
|
||||
stop[0], stop[1], stop[2], stop[3], stop[4])
|
||||
cr.rectangle(10.0, 0.0, 150.0, 42.0)
|
||||
cr.set_source(lg)
|
||||
cr.fill()
|
||||
|
||||
def get_save_gradient_text(self):
|
||||
return self.input_entry.get_text()
|
||||
|
||||
def get_compiled_gradient(self, new_id):
|
||||
# compiling gradient stops
|
||||
root = etree.Element("linearGradient", id=new_id)
|
||||
for idx, stop in enumerate(self.gradient_data["stops"]):
|
||||
stop_id = self.get_name() + str(idx)
|
||||
offset = stop[0]
|
||||
color = Color([stop[1], stop[2], stop[3]],"rgb")
|
||||
opacity = stop[4]
|
||||
tmp_stops = {
|
||||
"id": stop_id,
|
||||
"offset": str(offset),
|
||||
"style": Style({
|
||||
"stop-color": str(color),
|
||||
"stop-opacity": str(opacity)
|
||||
}).to_str()
|
||||
}
|
||||
current_stop = etree.SubElement(root, "stop", attrib=tmp_stops)
|
||||
return root
|
||||
|
||||
class LoadGradientTemplate(Gtk.FlowBoxChild):
|
||||
"""
|
||||
Template for generating gradient name
|
||||
and preview of saved gradient in the load page.
|
||||
"""
|
||||
def __init__(self, gradient_data):
|
||||
Gtk.FlowBoxChild.__init__(self)
|
||||
self.gradient_data = gradient_data
|
||||
self.set_size_request(60,32)
|
||||
self.set_halign(Gtk.Align.START)
|
||||
self.set_valign(Gtk.Align.START)
|
||||
container = Gtk.HBox()
|
||||
container.set_spacing(5)
|
||||
container.set_baseline_position(Gtk.BaselinePosition.TOP)
|
||||
self.checkbox = Gtk.CheckButton()
|
||||
self.checkbox.draw_indicator = True
|
||||
container.pack_start(self.checkbox,False,True,0)
|
||||
preview = Gtk.DrawingArea()
|
||||
preview.set_size_request(100, 32)
|
||||
preview.set_app_paintable(True)
|
||||
preview.connect("draw", self.on_draw, gradient_data)
|
||||
container.pack_start(preview,False,True,0)
|
||||
self.text_gradient = Gtk.Label()
|
||||
self.text_gradient.set_text(gradient_data.get("id"))
|
||||
self.text_gradient.set_line_wrap(True)
|
||||
self.text_gradient.set_line_wrap_mode(1)
|
||||
self.text_gradient.set_max_width_chars(25)
|
||||
container.pack_start(self.text_gradient,False,True,0)
|
||||
self.add(container)
|
||||
|
||||
def on_draw(self, wid, cr, data):
|
||||
"""
|
||||
Calllback for draw signal for rendering gradient.
|
||||
params:
|
||||
- wid :GtkWidget
|
||||
- cr :Cairo
|
||||
- data :list -> gradient data
|
||||
"""
|
||||
lg = cairo.LinearGradient(0.0, 20.0, 100.0, 20.0)
|
||||
for stop in data["stops"]:
|
||||
lg.add_color_stop_rgba(
|
||||
stop[0], stop[1], stop[2], stop[3], stop[4])
|
||||
cr.rectangle(10.0, 0.0, 110.0, 32.0)
|
||||
cr.set_source(lg)
|
||||
cr.fill()
|
||||
|
||||
class Handler:
|
||||
""" Signal Handler for GUI """
|
||||
|
||||
def __init__(self, main_window):
|
||||
self.main_window = main_window
|
||||
|
||||
def onDestroy(self, *args):
|
||||
Gtk.main_quit()
|
||||
|
||||
def onSwitchPage(self, notebook, page, page_num):
|
||||
if page_num == 0: # save tab
|
||||
pass
|
||||
elif page_num == 1: # load/remove tab
|
||||
self.main_window.gradients_to_load = []
|
||||
for children in self.main_window.load_container.get_children():
|
||||
self.main_window.load_container.remove(children)
|
||||
loaded_gradients = load_gradients_from_file()
|
||||
# TODO render with disabled checkbox if it already exists in current project doc
|
||||
for idx,gradient in enumerate(loaded_gradients):
|
||||
# parse gradient stops
|
||||
stop_data = read_stop_gradient(gradient)
|
||||
gradient_info = self.main_window.LoadGradientTemplate(stop_data)
|
||||
gradient_info.checkbox.connect("toggled",self.onLoadGradientToggled, gradient)
|
||||
gradient_info.set_name("gradient%d" % idx)
|
||||
self.main_window.load_container.add(gradient_info)
|
||||
self.main_window.load_container.show_all()
|
||||
else:
|
||||
pass
|
||||
|
||||
def onSaveGradientClicked(self, button):
|
||||
text = ""
|
||||
gradient_to_save = []
|
||||
# get all gradient data in save_container
|
||||
for item in self.main_window.save_container.get_children():
|
||||
# get new gradient name
|
||||
new_name_gradient = item.get_save_gradient_text()
|
||||
# strip all special chars
|
||||
if not new_name_gradient.isalnum():
|
||||
new_name_gradient = ''.join(e for e in new_name_gradient if e.isalnum())
|
||||
# get gradient data
|
||||
gradient_data = item.get_compiled_gradient(new_name_gradient)
|
||||
text += "{0}\n-----\n".format(etree.tostring(gradient_data))
|
||||
gradient_to_save.append(gradient_data)
|
||||
# save to file
|
||||
status = save_to_file(gradient_to_save)
|
||||
if status == 0:
|
||||
info = "%d gradients saved successfully!" % len(gradient_to_save)
|
||||
# reload current document info with saved gradients
|
||||
self.main_window.gradientSaver.reload_current_gradients(gradient_to_save)
|
||||
elif status == 1:
|
||||
info = "Nothing to save, there is no object with gradient selected. Exiting..."
|
||||
elif status == -1:
|
||||
info = "Internal Error (-1)! "
|
||||
# showing popup information
|
||||
self.main_window.get_object("information_text").set_text(info)
|
||||
self.main_window.information_dialog.set_title("Save Gradient Information")
|
||||
self.main_window.information_dialog.show_all()
|
||||
|
||||
def onLoadGradientToggled(self, togglebutton, gradient):
|
||||
# if active, queue gradient, otherwise pop it
|
||||
if togglebutton.get_active():
|
||||
self.main_window.gradients_to_load.append(gradient)
|
||||
else:
|
||||
self.main_window.gradients_to_load.remove(gradient)
|
||||
|
||||
def onLoadGradientClicked(self, button):
|
||||
if len(self.main_window.gradients_to_load) > 0:
|
||||
self.main_window.gradientSaver.insert_new_gradients_to_current_doc(self.main_window.gradients_to_load)
|
||||
teks = "Successfully loading these gradients:\n"
|
||||
teks += "".join(["- "+gradient.attrib["id"]+"\n" for gradient in self.main_window.gradients_to_load])
|
||||
else:
|
||||
teks = "No gradient(s) selected to load. Exiting..."
|
||||
self.main_window.get_object("information_text").set_text(teks)
|
||||
self.main_window.information_dialog.set_title("Load Gradient Information")
|
||||
self.main_window.information_dialog.show_all()
|
||||
|
||||
def onRemoveGradientClicked(self, button):
|
||||
loaded_gradients = load_gradients_from_file()
|
||||
if len(self.main_window.gradients_to_load) > 0:
|
||||
gradient_to_remove = [gradient.attrib["id"] for gradient in self.main_window.gradients_to_load]
|
||||
new_gradient_after = [gradient for gradient in loaded_gradients if gradient.attrib["id"] not in gradient_to_remove]
|
||||
create_new_file(new_gradient_after)
|
||||
teks = "Successfully removing these gradients:\n"
|
||||
teks += "".join(["- "+gradient+"\n" for gradient in gradient_to_remove])
|
||||
else:
|
||||
teks = "No gradient(s) selected to load. Exiting..."
|
||||
self.main_window.get_object("information_text").set_text(teks)
|
||||
self.main_window.information_dialog.set_title("Remove Gradient Information")
|
||||
self.main_window.information_dialog.show_all()
|
||||
|
||||
|
||||
class GradientSaver(inkex.Effect):
|
||||
def __init__(self):
|
||||
" define how the options are mapped from the inx file "
|
||||
inkex.Effect.__init__(self) # initialize the super class
|
||||
try:
|
||||
self.tty = open("/dev/tty", 'w')
|
||||
except:
|
||||
self.tty = open(os.devnull, 'w')
|
||||
self.doc_selected_gradients = []
|
||||
|
||||
def insert_new_gradients_to_current_doc(self, gradients):
|
||||
defs_node = self.svg.getElement("//svg:defs")
|
||||
for item in gradients:
|
||||
gradient = etree.SubElement(defs_node,item.tag,attrib=item.attrib)
|
||||
for stop in item:
|
||||
etree.SubElement(gradient,stop.tag,attrib=stop.attrib)
|
||||
|
||||
def reload_current_gradients(self, new_data):
|
||||
" reload gradients information in current project with stored gradient "
|
||||
for idx,gradient in enumerate(self.doc_selected_gradients):
|
||||
# set old gradient id to new id
|
||||
real_node = self.svg.getElement("//*[@id='%s']" % gradient["id"])
|
||||
# remove inkscape collect first
|
||||
real_node.attrib.pop("{"+NSS["inkscape"]+"}collect", None)
|
||||
real_node.attrib["id"] = new_data[idx].attrib["id"]
|
||||
# set old xlink:href to new id
|
||||
node_href = self.svg.getElement("//*[@xlink:href='#%s']" % gradient["id"])
|
||||
node_href.attrib["{"+NSS["xlink"]+"}href"] = "#"+new_data[idx].attrib["id"]
|
||||
# last set up inkscape collect again
|
||||
real_node.attrib["{"+NSS["inkscape"]+"}collect"] = "always"
|
||||
|
||||
def get_all_doc_gradients(self):
|
||||
"""TODO
|
||||
retrieve all gradient sources of current project document
|
||||
"""
|
||||
pass
|
||||
|
||||
def get_selected_gradients_data(self):
|
||||
selected_objects = self.svg.selected
|
||||
gradient_list = []
|
||||
if len(selected_objects) > 0:
|
||||
for item in selected_objects.values():
|
||||
style = Style(Style.parse_str(item.get('style')))
|
||||
fill = stroke = "None"
|
||||
if style.get("fill"):
|
||||
fill = style.get("fill")[5:-1] if "url" in style.get("fill") else "None"
|
||||
if style.get("stroke"):
|
||||
stroke = style("stroke")[5:-1] if "url" in style.get("stroke") else "None"
|
||||
if fill == "None" and stroke == "None":
|
||||
continue
|
||||
# read fill data
|
||||
if "radialGradient" in fill or "linearGradient" in fill:
|
||||
real_fill = self.svg.getElementById(fill).attrib["{"+NSS["xlink"]+"}href"][1:]
|
||||
real_fill_node = self.svg.getElementById(real_fill)
|
||||
if real_fill_node not in gradient_list:
|
||||
gradient_list.append(real_fill_node)
|
||||
# read stroke data
|
||||
if "radialGradient" in stroke or "linearGradient" in stroke:
|
||||
real_stroke = self.svg.getElementById(stroke).attrib["{"+NSS["xlink"]+"}href"][1:]
|
||||
real_stroke_node = self.svg.getElementById(real_stroke)
|
||||
if real_stroke_node not in gradient_list:
|
||||
gradient_list.append(real_stroke_node)
|
||||
data = []
|
||||
# read gradients data
|
||||
for gradient in gradient_list:
|
||||
# parse gradient stops
|
||||
stop_data = read_stop_gradient(gradient)
|
||||
inkex.utils.debug(gradient)
|
||||
data.append(stop_data)
|
||||
return data
|
||||
|
||||
# called when the extension is running.
|
||||
def effect(self):
|
||||
self.doc_selected_gradients = self.get_selected_gradients_data()
|
||||
try:
|
||||
app = MainWindow(self)
|
||||
Gtk.main()
|
||||
except Exception as e:
|
||||
import traceback
|
||||
show_errormsg(e)
|
||||
show_errormsg(traceback.print_exc())
|
||||
|
||||
|
||||
if __name__ == '__main__':
|
||||
GradientSaver().run()
|
678
extensions/fablabchemnitz/gradient_saver/icon.svg
Normal file
678
extensions/fablabchemnitz/gradient_saver/icon.svg
Normal file
@ -0,0 +1,678 @@
|
||||
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
|
||||
<!-- Created with Inkscape (http://www.inkscape.org/) -->
|
||||
|
||||
<svg
|
||||
xmlns:dc="http://purl.org/dc/elements/1.1/"
|
||||
xmlns:cc="http://creativecommons.org/ns#"
|
||||
xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
|
||||
xmlns:svg="http://www.w3.org/2000/svg"
|
||||
xmlns="http://www.w3.org/2000/svg"
|
||||
xmlns:xlink="http://www.w3.org/1999/xlink"
|
||||
xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"
|
||||
xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
|
||||
width="256"
|
||||
height="256"
|
||||
viewBox="0 0 67.733332 67.733335"
|
||||
version="1.1"
|
||||
id="svg8"
|
||||
inkscape:version="0.92.4 (5da689c313, 2019-01-14)"
|
||||
sodipodi:docname="icon.svg">
|
||||
<title
|
||||
id="title239">Gradient Saver Icon</title>
|
||||
<defs
|
||||
id="defs2">
|
||||
<linearGradient
|
||||
id="linearGradient5327"
|
||||
inkscape:collect="always">
|
||||
<stop
|
||||
id="stop5323"
|
||||
offset="0"
|
||||
style="stop-color:#35f600;stop-opacity:1" />
|
||||
<stop
|
||||
id="stop5325"
|
||||
offset="1"
|
||||
style="stop-color:#f0f600;stop-opacity:1" />
|
||||
</linearGradient>
|
||||
<linearGradient
|
||||
inkscape:collect="always"
|
||||
id="linearGradient4992">
|
||||
<stop
|
||||
style="stop-color:#00bfa5;stop-opacity:1"
|
||||
offset="0"
|
||||
id="stop4988" />
|
||||
<stop
|
||||
style="stop-color:#29ff8a;stop-opacity:1"
|
||||
offset="1"
|
||||
id="stop4990" />
|
||||
</linearGradient>
|
||||
<linearGradient
|
||||
id="linearGradient4978"
|
||||
inkscape:collect="always">
|
||||
<stop
|
||||
id="stop4974"
|
||||
offset="0"
|
||||
style="stop-color:#6200ea;stop-opacity:1" />
|
||||
<stop
|
||||
id="stop4976"
|
||||
offset="1"
|
||||
style="stop-color:#f50048;stop-opacity:1" />
|
||||
</linearGradient>
|
||||
<linearGradient
|
||||
inkscape:collect="always"
|
||||
id="linearGradient4972">
|
||||
<stop
|
||||
style="stop-color:#00c853;stop-opacity:1"
|
||||
offset="0"
|
||||
id="stop4968" />
|
||||
<stop
|
||||
style="stop-color:#2196f3;stop-opacity:1"
|
||||
offset="1"
|
||||
id="stop4970" />
|
||||
</linearGradient>
|
||||
<linearGradient
|
||||
inkscape:collect="always"
|
||||
id="linearGradient4977">
|
||||
<stop
|
||||
style="stop-color:#fdd835;stop-opacity:1"
|
||||
offset="0"
|
||||
id="stop4973" />
|
||||
<stop
|
||||
style="stop-color:#f50057;stop-opacity:1"
|
||||
offset="1"
|
||||
id="stop4975" />
|
||||
</linearGradient>
|
||||
<linearGradient
|
||||
id="linearGradient4851"
|
||||
inkscape:collect="always">
|
||||
<stop
|
||||
id="stop4847"
|
||||
offset="0"
|
||||
style="stop-color:#1de9b6;stop-opacity:1" />
|
||||
<stop
|
||||
id="stop4849"
|
||||
offset="1"
|
||||
style="stop-color:#2962ff;stop-opacity:1" />
|
||||
</linearGradient>
|
||||
<linearGradient
|
||||
inkscape:collect="always"
|
||||
id="linearGradient4753">
|
||||
<stop
|
||||
style="stop-color:#d500f9;stop-opacity:1"
|
||||
offset="0"
|
||||
id="stop4749" />
|
||||
<stop
|
||||
style="stop-color:#6200ea;stop-opacity:1"
|
||||
offset="1"
|
||||
id="stop4751" />
|
||||
</linearGradient>
|
||||
<linearGradient
|
||||
inkscape:collect="always"
|
||||
xlink:href="#linearGradient4753"
|
||||
id="linearGradient4755"
|
||||
x1="114.52679"
|
||||
y1="122.37501"
|
||||
x2="85.328125"
|
||||
y2="153.12674"
|
||||
gradientUnits="userSpaceOnUse"
|
||||
gradientTransform="translate(8.3154762)" />
|
||||
<linearGradient
|
||||
inkscape:collect="always"
|
||||
xlink:href="#linearGradient4851"
|
||||
id="linearGradient4845"
|
||||
gradientUnits="userSpaceOnUse"
|
||||
gradientTransform="translate(8.3154762)"
|
||||
x1="115.28274"
|
||||
y1="124.26488"
|
||||
x2="75.122765"
|
||||
y2="157.66246" />
|
||||
<linearGradient
|
||||
inkscape:collect="always"
|
||||
xlink:href="#linearGradient4851"
|
||||
id="linearGradient4834"
|
||||
x1="-372.85895"
|
||||
y1="77.110123"
|
||||
x2="-317.53687"
|
||||
y2="46.030495"
|
||||
gradientUnits="userSpaceOnUse"
|
||||
gradientTransform="matrix(0.7490779,0,0,0.7490779,-28.486614,89.363651)" />
|
||||
<linearGradient
|
||||
inkscape:collect="always"
|
||||
xlink:href="#linearGradient4977"
|
||||
id="linearGradient4932"
|
||||
x1="-81.856453"
|
||||
y1="213.70543"
|
||||
x2="-83.746712"
|
||||
y2="278.80466"
|
||||
gradientUnits="userSpaceOnUse"
|
||||
gradientTransform="matrix(0.63636261,0,0,0.63636261,-11.36592,145.37946)" />
|
||||
<linearGradient
|
||||
inkscape:collect="always"
|
||||
xlink:href="#linearGradient4977"
|
||||
id="linearGradient4940"
|
||||
x1="-101.17622"
|
||||
y1="231.34521"
|
||||
x2="-115.24634"
|
||||
y2="199.42558"
|
||||
gradientUnits="userSpaceOnUse" />
|
||||
<linearGradient
|
||||
inkscape:collect="always"
|
||||
xlink:href="#linearGradient4977"
|
||||
id="linearGradient4952"
|
||||
x1="-61.471992"
|
||||
y1="208.40015"
|
||||
x2="-50.513939"
|
||||
y2="218.02187"
|
||||
gradientUnits="userSpaceOnUse"
|
||||
gradientTransform="matrix(0.8245614,0,0,1,-10.503224,0)" />
|
||||
<linearGradient
|
||||
inkscape:collect="always"
|
||||
xlink:href="#linearGradient4978"
|
||||
id="linearGradient4958"
|
||||
gradientUnits="userSpaceOnUse"
|
||||
gradientTransform="matrix(0.8245614,0,0,1,77.718339,5.7980475)"
|
||||
x1="-61.359409"
|
||||
y1="232.67445"
|
||||
x2="-53.959938"
|
||||
y2="206.80617" />
|
||||
<linearGradient
|
||||
inkscape:collect="always"
|
||||
xlink:href="#linearGradient4851"
|
||||
id="linearGradient4962"
|
||||
gradientUnits="userSpaceOnUse"
|
||||
gradientTransform="matrix(0.8245614,0,0,1,157.24809,-18.087736)"
|
||||
x1="-61.471992"
|
||||
y1="208.40015"
|
||||
x2="-50.513939"
|
||||
y2="218.02187" />
|
||||
<linearGradient
|
||||
inkscape:collect="always"
|
||||
xlink:href="#linearGradient4972"
|
||||
id="linearGradient4966"
|
||||
gradientUnits="userSpaceOnUse"
|
||||
gradientTransform="matrix(0.8245614,0,0,1,226.92887,-70.453899)"
|
||||
x1="-61.471992"
|
||||
y1="208.40015"
|
||||
x2="-52.248871"
|
||||
y2="224.28619" />
|
||||
<linearGradient
|
||||
inkscape:collect="always"
|
||||
xlink:href="#linearGradient4992"
|
||||
id="linearGradient4986"
|
||||
gradientUnits="userSpaceOnUse"
|
||||
gradientTransform="matrix(0.8245614,0,0,1,225.00896,-68.355136)"
|
||||
x1="-47.505936"
|
||||
y1="221.68723"
|
||||
x2="-56.489384"
|
||||
y2="202.32527" />
|
||||
<linearGradient
|
||||
inkscape:collect="always"
|
||||
xlink:href="#linearGradient4977"
|
||||
id="linearGradient5011"
|
||||
gradientUnits="userSpaceOnUse"
|
||||
x1="-131.41586"
|
||||
y1="199.4256"
|
||||
x2="-125.32622"
|
||||
y2="216.22539"
|
||||
gradientTransform="matrix(0.40495803,0,0,0.40495803,146.66448,176.80023)" />
|
||||
<linearGradient
|
||||
inkscape:collect="always"
|
||||
xlink:href="#linearGradient4851"
|
||||
id="linearGradient5305"
|
||||
gradientUnits="userSpaceOnUse"
|
||||
gradientTransform="matrix(0.40495803,0,0,0.40495803,71.206797,177.92807)"
|
||||
x1="-134.1552"
|
||||
y1="187.01805"
|
||||
x2="-125.32622"
|
||||
y2="216.22539" />
|
||||
<linearGradient
|
||||
inkscape:collect="always"
|
||||
xlink:href="#linearGradient4978"
|
||||
id="linearGradient5309"
|
||||
gradientUnits="userSpaceOnUse"
|
||||
gradientTransform="matrix(0.8245614,0,0,1,77.145743,4.2945512)"
|
||||
x1="-53.819473"
|
||||
y1="237.63091"
|
||||
x2="-52.285004"
|
||||
y2="209.06267" />
|
||||
<linearGradient
|
||||
inkscape:collect="always"
|
||||
xlink:href="#linearGradient4851"
|
||||
id="linearGradient5311"
|
||||
gradientUnits="userSpaceOnUse"
|
||||
gradientTransform="matrix(0.8245614,0,0,1,156.2106,-19.317359)"
|
||||
x1="-52.407578"
|
||||
y1="211.81105"
|
||||
x2="-56.196835"
|
||||
y2="236.80499" />
|
||||
<linearGradient
|
||||
inkscape:collect="always"
|
||||
xlink:href="#linearGradient4851"
|
||||
id="linearGradient5315"
|
||||
gradientUnits="userSpaceOnUse"
|
||||
gradientTransform="matrix(0.40495803,0,0,0.40495803,71.206797,177.92807)"
|
||||
x1="-43.361553"
|
||||
y1="209.01698"
|
||||
x2="-84.406708"
|
||||
y2="287.03156" />
|
||||
<linearGradient
|
||||
inkscape:collect="always"
|
||||
id="linearGradient3883">
|
||||
<stop
|
||||
style="stop-color:#dddbd8;stop-opacity:1"
|
||||
offset="0"
|
||||
id="stop3879" />
|
||||
<stop
|
||||
style="stop-color:#f5f4f2;stop-opacity:1"
|
||||
offset="1"
|
||||
id="stop3881" />
|
||||
</linearGradient>
|
||||
<linearGradient
|
||||
id="linearGradient3094"
|
||||
inkscape:collect="always">
|
||||
<stop
|
||||
id="stop3090"
|
||||
offset="0"
|
||||
style="stop-color:#0b394d;stop-opacity:1;" />
|
||||
<stop
|
||||
id="stop3092"
|
||||
offset="1"
|
||||
style="stop-color:#0b394d;stop-opacity:0;" />
|
||||
</linearGradient>
|
||||
<linearGradient
|
||||
id="linearGradient2639"
|
||||
inkscape:collect="always">
|
||||
<stop
|
||||
id="stop2635"
|
||||
offset="0"
|
||||
style="stop-color:#fe6a2d;stop-opacity:1" />
|
||||
<stop
|
||||
id="stop2637"
|
||||
offset="1"
|
||||
style="stop-color:#9b0101;stop-opacity:1" />
|
||||
</linearGradient>
|
||||
<clipPath
|
||||
id="clipPath2609"
|
||||
clipPathUnits="userSpaceOnUse">
|
||||
<rect
|
||||
ry="10.056858"
|
||||
rx="10.056858"
|
||||
y="-85.398689"
|
||||
x="1592.8157"
|
||||
height="58.391529"
|
||||
width="90.441025"
|
||||
id="rect2611"
|
||||
style="opacity:1;vector-effect:none;fill:#3d83cf;fill-opacity:1;stroke:none;stroke-width:1.5;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;paint-order:stroke fill markers" />
|
||||
</clipPath>
|
||||
<linearGradient
|
||||
gradientUnits="userSpaceOnUse"
|
||||
y2="246.60634"
|
||||
x2="643.51672"
|
||||
y1="257.47424"
|
||||
x1="643.51672"
|
||||
id="linearGradient1561-1"
|
||||
xlink:href="#linearGradient3883"
|
||||
inkscape:collect="always" />
|
||||
<filter
|
||||
height="1.1218587"
|
||||
y="-0.060929373"
|
||||
width="1.0463915"
|
||||
x="-0.02319574"
|
||||
id="filter3130-5"
|
||||
style="color-interpolation-filters:sRGB"
|
||||
inkscape:collect="always">
|
||||
<feGaussianBlur
|
||||
id="feGaussianBlur3132-3"
|
||||
stdDeviation="0.45051951"
|
||||
inkscape:collect="always" />
|
||||
</filter>
|
||||
<linearGradient
|
||||
gradientTransform="matrix(1,0,-0.26717917,-0.37367534,29.058353,152.44235)"
|
||||
gradientUnits="userSpaceOnUse"
|
||||
y2="166.3714"
|
||||
x2="1384.7688"
|
||||
y1="-3.469604"
|
||||
x1="1362.2035"
|
||||
id="linearGradient3096-8"
|
||||
xlink:href="#linearGradient3094"
|
||||
inkscape:collect="always" />
|
||||
<linearGradient
|
||||
gradientUnits="userSpaceOnUse"
|
||||
y2="-94.958282"
|
||||
x2="1617.5334"
|
||||
y1="-135.36632"
|
||||
x1="1615.9795"
|
||||
id="linearGradient2641-1"
|
||||
xlink:href="#linearGradient2639"
|
||||
inkscape:collect="always" />
|
||||
<linearGradient
|
||||
gradientUnits="userSpaceOnUse"
|
||||
y2="-549.33533"
|
||||
x2="1543.2006"
|
||||
y1="-489.51007"
|
||||
x1="1540.6981"
|
||||
id="linearGradient2649-6"
|
||||
xlink:href="#linearGradient4977"
|
||||
inkscape:collect="always"
|
||||
gradientTransform="matrix(0.39357722,0,0,0.39357722,-545.58139,422.10485)" />
|
||||
<linearGradient
|
||||
gradientUnits="userSpaceOnUse"
|
||||
y2="-869.45026"
|
||||
x2="1369.0061"
|
||||
y1="-928.71313"
|
||||
x1="1365.6919"
|
||||
id="linearGradient2657-3"
|
||||
xlink:href="#linearGradient4851"
|
||||
inkscape:collect="always"
|
||||
gradientTransform="matrix(0.39357722,0,0,0.39357722,-417.74238,548.92883)" />
|
||||
<linearGradient
|
||||
gradientUnits="userSpaceOnUse"
|
||||
y2="-1259.3573"
|
||||
x2="1095.538"
|
||||
y1="-1193.1265"
|
||||
x1="1094.515"
|
||||
id="linearGradient2665-6"
|
||||
xlink:href="#linearGradient4851"
|
||||
inkscape:collect="always"
|
||||
gradientTransform="matrix(0.39357722,0,0,0.39357722,-261.43492,638.34422)" />
|
||||
<linearGradient
|
||||
gradientUnits="userSpaceOnUse"
|
||||
y2="-1459.3491"
|
||||
x2="748.05066"
|
||||
y1="-1503.9033"
|
||||
x1="745.37823"
|
||||
id="linearGradient2673-8"
|
||||
xlink:href="#linearGradient5327"
|
||||
inkscape:collect="always"
|
||||
gradientTransform="matrix(0.39357722,0,0,0.39357722,-87.311101,684.2575)" />
|
||||
<linearGradient
|
||||
gradientUnits="userSpaceOnUse"
|
||||
y2="-1645.3777"
|
||||
x2="352.32254"
|
||||
y1="-1596.4655"
|
||||
x1="361.24866"
|
||||
id="linearGradient2681-9"
|
||||
xlink:href="#linearGradient5327"
|
||||
inkscape:collect="always"
|
||||
gradientTransform="matrix(0.39357722,0,0,0.39357722,92.762826,683.53977)" />
|
||||
<clipPath
|
||||
id="clipPath2609-4"
|
||||
clipPathUnits="userSpaceOnUse">
|
||||
<rect
|
||||
ry="10.056858"
|
||||
rx="10.056858"
|
||||
y="-85.398689"
|
||||
x="1592.8157"
|
||||
height="58.391529"
|
||||
width="90.441025"
|
||||
id="rect2611-0"
|
||||
style="opacity:1;vector-effect:none;fill:#3d83cf;fill-opacity:1;stroke:none;stroke-width:1.5;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;paint-order:stroke fill markers" />
|
||||
</clipPath>
|
||||
<linearGradient
|
||||
inkscape:collect="always"
|
||||
xlink:href="#linearGradient4977"
|
||||
id="linearGradient5566"
|
||||
gradientUnits="userSpaceOnUse"
|
||||
x1="1615.9795"
|
||||
y1="-135.36632"
|
||||
x2="1617.5334"
|
||||
y2="-94.958282"
|
||||
gradientTransform="matrix(0.39357722,0,0,0.39357722,-636.23993,266.51512)" />
|
||||
<linearGradient
|
||||
inkscape:collect="always"
|
||||
xlink:href="#linearGradient4851"
|
||||
id="linearGradient5674"
|
||||
gradientUnits="userSpaceOnUse"
|
||||
gradientTransform="matrix(0.39357722,0,0,0.39357722,-417.74238,548.92883)"
|
||||
x1="1365.6919"
|
||||
y1="-928.71313"
|
||||
x2="1368.8816"
|
||||
y2="-878.95062" />
|
||||
<linearGradient
|
||||
inkscape:collect="always"
|
||||
xlink:href="#linearGradient4851"
|
||||
id="linearGradient5676"
|
||||
gradientUnits="userSpaceOnUse"
|
||||
gradientTransform="matrix(0.39357722,0,0,0.39357722,-261.43492,638.34422)"
|
||||
x1="1094.515"
|
||||
y1="-1193.1265"
|
||||
x2="1098.1172"
|
||||
y2="-1263.8123" />
|
||||
<linearGradient
|
||||
inkscape:collect="always"
|
||||
xlink:href="#linearGradient5327"
|
||||
id="linearGradient5678"
|
||||
gradientUnits="userSpaceOnUse"
|
||||
gradientTransform="matrix(0.39357722,0,0,0.39357722,92.762826,683.53977)"
|
||||
x1="361.24866"
|
||||
y1="-1596.4655"
|
||||
x2="352.32254"
|
||||
y2="-1645.3777" />
|
||||
<linearGradient
|
||||
inkscape:collect="always"
|
||||
xlink:href="#linearGradient4851"
|
||||
id="linearGradient5694"
|
||||
gradientUnits="userSpaceOnUse"
|
||||
gradientTransform="matrix(0.39357722,0,0,0.39357722,-261.43492,638.34422)"
|
||||
x1="1094.515"
|
||||
y1="-1193.1265"
|
||||
x2="1098.1172"
|
||||
y2="-1263.8123" />
|
||||
</defs>
|
||||
<sodipodi:namedview
|
||||
id="base"
|
||||
pagecolor="#ffffff"
|
||||
bordercolor="#666666"
|
||||
borderopacity="1.0"
|
||||
inkscape:pageopacity="0.0"
|
||||
inkscape:pageshadow="2"
|
||||
inkscape:zoom="2.0273438"
|
||||
inkscape:cx="34.014139"
|
||||
inkscape:cy="85.816088"
|
||||
inkscape:document-units="mm"
|
||||
inkscape:current-layer="layer1"
|
||||
showgrid="false"
|
||||
inkscape:window-width="1366"
|
||||
inkscape:window-height="712"
|
||||
inkscape:window-x="0"
|
||||
inkscape:window-y="28"
|
||||
inkscape:window-maximized="1"
|
||||
inkscape:snap-global="false"
|
||||
units="px" />
|
||||
<metadata
|
||||
id="metadata5">
|
||||
<rdf:RDF>
|
||||
<cc:Work
|
||||
rdf:about="">
|
||||
<dc:format>image/svg+xml</dc:format>
|
||||
<dc:type
|
||||
rdf:resource="http://purl.org/dc/dcmitype/StillImage" />
|
||||
<dc:title>Gradient Saver Icon</dc:title>
|
||||
<dc:creator>
|
||||
<cc:Agent>
|
||||
<dc:title>Hadiid Pratama</dc:title>
|
||||
</cc:Agent>
|
||||
</dc:creator>
|
||||
<cc:license
|
||||
rdf:resource="http://creativecommons.org/licenses/by-nc/4.0/" />
|
||||
</cc:Work>
|
||||
<cc:License
|
||||
rdf:about="http://creativecommons.org/licenses/by-nc/4.0/">
|
||||
<cc:permits
|
||||
rdf:resource="http://creativecommons.org/ns#Reproduction" />
|
||||
<cc:permits
|
||||
rdf:resource="http://creativecommons.org/ns#Distribution" />
|
||||
<cc:requires
|
||||
rdf:resource="http://creativecommons.org/ns#Notice" />
|
||||
<cc:requires
|
||||
rdf:resource="http://creativecommons.org/ns#Attribution" />
|
||||
<cc:prohibits
|
||||
rdf:resource="http://creativecommons.org/ns#CommercialUse" />
|
||||
<cc:permits
|
||||
rdf:resource="http://creativecommons.org/ns#DerivativeWorks" />
|
||||
</cc:License>
|
||||
</rdf:RDF>
|
||||
</metadata>
|
||||
<g
|
||||
inkscape:label="Layer 1"
|
||||
inkscape:groupmode="layer"
|
||||
id="layer1"
|
||||
transform="translate(0,-229.26665)">
|
||||
<g
|
||||
id="g226"
|
||||
transform="translate(-4.7231367,-1.696596)">
|
||||
<path
|
||||
style="opacity:0.66799999;vector-effect:none;fill:none;fill-opacity:1;stroke:none;stroke-width:1.62901139;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;paint-order:stroke fill markers;filter:url(#filter3130-5)"
|
||||
d="m 1365.4604,94.01541 c -0.7804,0 -1.241,0.234791 -1.0325,0.526396 l 4.7725,6.674764 -3.582,0.3862 c -0.8145,0.0879 -1.363,0.36813 -1.4493,0.69362 -0.027,0.0194 -0.053,0.0388 -0.075,0.0593 -0.1454,0.13326 -0.1905,0.28935 -0.115,0.45823 0,0 2e-4,1.9e-4 2e-4,1.9e-4 0.013,0.0337 0.034,0.0681 0.06,0.10273 l 5.6074,7.84226 c 0.05,0.0694 0.1169,0.13701 0.1986,0.20238 0,0 2e-4,1.9e-4 2e-4,1.9e-4 0.1644,0.13066 0.3904,0.25203 0.6592,0.35859 0.2019,0.08 0.424,0.15162 0.6691,0.2128 0.5654,0.14275 1.2217,0.22825 1.8718,0.22825 h 35.4505 c 0.093,-10e-6 0.1828,-0.002 0.2714,-0.005 0.2636,-0.0102 0.5048,-0.0355 0.7186,-0.0734 0.071,-0.0126 0.1394,-0.0267 0.2044,-0.0421 0.065,-0.0153 0.1267,-0.0323 0.1852,-0.0502 0.117,-0.0359 0.2203,-0.077 0.3091,-0.12223 0.2664,-0.13583 0.4003,-0.31088 0.3673,-0.5069 -0.01,-0.0327 -0.016,-0.0659 -0.031,-0.0996 -0.013,-0.0338 -0.034,-0.068 -0.06,-0.10273 l -1.7115,-2.39388 -2.1839,-3.05449 -1.7117,-2.39389 c -0.025,-0.0347 -0.049,-0.0692 -0.087,-0.10292 -0.033,-0.0338 -0.071,-0.067 -0.1115,-0.0996 -0.1645,-0.13073 -0.3903,-0.25198 -0.6593,-0.35859 -0.1345,-0.0533 -0.2798,-0.10301 -0.4344,-0.1483 -0.1537,-0.0453 -0.3151,-0.0863 -0.4838,-0.12224 0,0 -5e-4,0 -5e-4,0 -0.085,-0.0179 -0.1699,-0.0346 -0.2563,-0.05 0,0 -6e-4,0 -6e-4,0 -0.087,-0.0154 -0.1754,-0.0295 -0.2642,-0.0421 0,0 -6e-4,0 -6e-4,0 -0.2676,-0.0379 -0.5445,-0.0631 -0.823,-0.0734 0,0 -5e-4,0 -5e-4,0 -0.091,-0.003 -0.1849,-0.005 -0.2776,-0.005 h -5e-4 -1.3436 l -0.4127,-0.28792 -1.2344,-0.8622 c -0.2629,-0.18344 -0.7316,-0.31729 -1.2196,-0.36786 0.1127,-0.15515 -0.014,-0.34839 -0.3868,-0.512876 l -3.3931,-1.501175 c -0.3716,-0.164436 -0.8912,-0.257825 -1.3664,-0.263004 0,-0.01412 -0.01,-0.02836 -0.011,-0.04268 8e-4,-0.0059 0,-0.01166 0,-0.01757 10e-5,-7.23e-4 10e-5,-0.0011 -0.01,-0.0019 -0.062,-0.153559 -0.3058,-0.313129 -0.7073,-0.431393 l -4.1571,-1.225809 c -0.4553,-0.13428 -0.9904,-0.180421 -1.4201,-0.139807 -0.01,-0.0087 -0.012,-0.01741 -0.018,-0.02608 -0.03,-0.0287 -0.06,-0.05691 -0.099,-0.08477 -0.01,-0.0071 -0.019,-0.01405 -0.029,-0.02104 -0.041,-0.02773 -0.086,-0.05499 -0.1391,-0.0811 -0.1806,-0.09206 -0.4333,-0.172313 -0.7282,-0.227476 l -4.6375,-0.866642 c -0.5082,-0.09498 -1.0223,-0.09104 -1.3778,-0.0073 -0.019,-0.0099 -0.031,-0.01951 -0.047,-0.02915 -0.042,-0.02496 -0.089,-0.04916 -0.1403,-0.07241 -0.012,-0.0039 -0.013,-0.0081 -0.024,-0.01196 -0.063,-0.02608 -0.1242,-0.0504 -0.1935,-0.07357 -0.052,-0.01835 -0.113,-0.03595 -0.1693,-0.05214 -3e-4,-3.74e-4 10e-5,-7.23e-4 2e-4,-0.0015 -0.1984,-0.0536 -0.4223,-0.09456 -0.6608,-0.116829 l -4.8017,-0.448769 c -0.5254,-0.04909 -0.9827,0.0045 -1.2396,0.125132 -0.01,-0.0026 -0.015,-0.0052 -0.023,-0.0079 -0.01,-0.0068 -0.037,-0.01312 -0.046,-0.01969 -0.059,-0.02074 -0.1157,-0.04038 -0.1681,-0.05871 -0.018,-0.0065 -0.046,-0.01255 -0.064,-0.01872 -0.056,-0.01555 -0.1122,-0.02975 -0.1713,-0.04306 -0.038,-0.0086 -0.076,-0.0173 -0.1133,-0.02492 -0.02,-0.0033 -0.033,-0.0065 -0.049,-0.0095 -0.07,-0.0127 -0.1414,-0.02354 -0.2141,-0.03284 -0.014,-0.0015 -0.025,-0.003 -0.036,-0.0045 -0.078,-0.0092 -0.1542,-0.01629 -0.2326,-0.02123 -3e-4,-1.83e-4 -0.012,-7.23e-4 -0.012,-7.23e-4 v 0 c 0,0 -5e-4,1.91e-4 -5e-4,1.91e-4 -0.08,-0.0048 -0.1603,-0.0079 -0.2406,-0.0079 z"
|
||||
id="path140"
|
||||
inkscape:connector-curvature="0"
|
||||
inkscape:transform-center-y="-7.3219625"
|
||||
inkscape:transform-center-x="3.5474848"
|
||||
transform="matrix(-1.0159411,0,0,0.83457554,1450.0893,194.42636)" />
|
||||
<g
|
||||
id="g108">
|
||||
<path
|
||||
inkscape:connector-curvature="0"
|
||||
id="path5277"
|
||||
d="m 32.026687,256.94379 c 1.01979,0.89055 2.70444,2.74573 4.10309,4.082 h 11.51227 c 0.95662,0 1.72654,0.92699 1.72654,2.07834 v 20.76027 c 0,1.15134 -0.76992,2.078 -1.72654,2.078 h -29.96732 c -0.95661,0 -1.72681,-0.92666 -1.72681,-2.078 v -4.08201 -16.67826 -4.08202 c 0,-1.15134 0.7702,-2.07832 1.72681,-2.07832 z"
|
||||
style="opacity:1;fill:url(#linearGradient5305);fill-opacity:1;stroke:none;stroke-width:5.29166698;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;paint-order:markers fill stroke" />
|
||||
<g
|
||||
id="g5672"
|
||||
transform="translate(21.664226,27.145537)">
|
||||
<g
|
||||
id="g5692"
|
||||
transform="matrix(1.0615763,0,0,1.0615763,0.14058954,-15.029605)"
|
||||
style="stroke-width:0.94199538">
|
||||
<rect
|
||||
style="opacity:1;vector-effect:none;fill:url(#linearGradient5566);fill-opacity:1;stroke:none;stroke-width:1.41299284;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;paint-order:stroke fill markers"
|
||||
id="rect2615-1"
|
||||
width="7.575388"
|
||||
height="30.240459"
|
||||
x="-2.1066508"
|
||||
y="212.28931"
|
||||
rx="1.4310507"
|
||||
ry="1.4310507" />
|
||||
<path
|
||||
id="rect2771-2"
|
||||
d="m 4.2772194,212.31071 c -0.1958741,0.17826 -0.3454332,0.41238 -0.4193576,0.68827 l -5.9644127,22.25932 v 5.8405 c 0,0.0437 0.00255,0.0867 0.00643,0.12936 l 4.4366992,1.1889 c 0.7657856,0.2052 1.5473532,-0.24613 1.7525436,-1.01191 l 1.3796344,-5.14891 v -22.53582 c 0,-0.71093 -0.5138192,-1.29614 -1.1915118,-1.40971 z"
|
||||
style="opacity:0.072;vector-effect:none;fill:#000000;fill-opacity:1;stroke:none;stroke-width:1.41299295;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;paint-order:stroke fill markers"
|
||||
inkscape:connector-curvature="0" />
|
||||
<rect
|
||||
ry="1.4310507"
|
||||
rx="1.4310507"
|
||||
y="203.67245"
|
||||
x="59.982849"
|
||||
height="30.240459"
|
||||
width="7.575388"
|
||||
id="rect2617-8"
|
||||
style="opacity:1;vector-effect:none;fill:url(#linearGradient2649-6);fill-opacity:1;stroke:none;stroke-width:1.41299284;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;paint-order:stroke fill markers"
|
||||
inkscape:transform-center-y="-31.186035"
|
||||
transform="rotate(15)"
|
||||
inkscape:transform-center-x="-8.3563328" />
|
||||
<path
|
||||
id="rect2773-9"
|
||||
d="m 11.572926,214.03246 c -0.393519,0.0754 -0.753243,0.31411 -0.970224,0.68993 l -11.26801895,19.51689 -1.56632555,5.84571 c -0.042118,0.15715 -0.055255,0.31455 -0.045017,0.46793 l 3.23713258,1.86888 1.68906372,0.45253 c 0.3353405,-0.10159 0.6346651,-0.32511 0.8244981,-0.65392 l 2.9198911,-5.05721 5.77771,-21.56299 c 0.164698,-0.61466 -0.09438,-1.23894 -0.59871,-1.56775 z"
|
||||
style="opacity:0.072;vector-effect:none;fill:#000000;fill-opacity:1;stroke:none;stroke-width:1.41299295;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;paint-order:stroke fill markers"
|
||||
inkscape:connector-curvature="0" />
|
||||
<rect
|
||||
inkscape:transform-center-x="-16.143173"
|
||||
transform="rotate(30)"
|
||||
inkscape:transform-center-y="-27.960618"
|
||||
style="opacity:1;vector-effect:none;fill:url(#linearGradient5674);fill-opacity:1;stroke:none;stroke-width:1.41299284;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;paint-order:stroke fill markers"
|
||||
id="rect2619-3"
|
||||
width="7.575388"
|
||||
height="30.240459"
|
||||
x="117.72649"
|
||||
y="179.27925"
|
||||
rx="1.4310507"
|
||||
ry="1.4310507" />
|
||||
<path
|
||||
id="rect2775-6"
|
||||
d="m 17.683283,217.71241 c -0.365801,0 -0.731626,0.14025 -1.011917,0.42055 l -15.78529029,15.78528 -2.97627451,5.15507 c -0.1559156,0.27006 -0.2130632,0.5686 -0.1848109,0.85578 l 1.63243777,1.63243 2.79905733,1.61608 c 0.1863394,-0.0697 0.3616641,-0.17828 0.5119996,-0.32862 l 4.279619,-4.27962 11.211405,-19.4188 c 0.246508,-0.42696 0.248885,-0.92538 0.05069,-1.33674 -0.169005,-0.0671 -0.347896,-0.10141 -0.52692,-0.10141 z"
|
||||
style="opacity:0.072;vector-effect:none;fill:#000000;fill-opacity:1;stroke:none;stroke-width:1.41299295;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;paint-order:stroke fill markers"
|
||||
inkscape:connector-curvature="0" />
|
||||
<rect
|
||||
ry="1.4310507"
|
||||
rx="1.4310507"
|
||||
y="140.77209"
|
||||
x="167.18912"
|
||||
height="30.240459"
|
||||
width="7.575388"
|
||||
id="rect2621-8"
|
||||
style="opacity:1;vector-effect:none;fill:url(#linearGradient5694);fill-opacity:1;stroke:none;stroke-width:1.41299284;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;paint-order:stroke fill markers"
|
||||
inkscape:transform-center-y="-22.829713"
|
||||
transform="rotate(45)"
|
||||
inkscape:transform-center-x="-22.829829" />
|
||||
<path
|
||||
id="rect2777-0"
|
||||
d="m 22.328484,222.8054 c -0.230592,0.006 -0.463295,0.0685 -0.67785,0.19239 l -19.4190475,11.21164 -3.9232803,3.92328 c -0.3915541,0.39155 -0.5086758,0.94976 -0.3532575,1.44194 l 0.3056446,0.52906 c 0.015928,0.0176 0.030654,0.0359 0.047613,0.0528 l 3.1947359,3.19473 c 0.076472,-0.0281 0.1519974,-0.0616 0.2250726,-0.10378 l 5.1550659,-2.97628 16.1411553,-16.14115 c 0.237871,-0.23787 0.373637,-0.53753 0.409641,-0.8463 -0.283955,-0.31965 -0.691327,-0.48954 -1.105493,-0.47836 z"
|
||||
style="opacity:0.072;vector-effect:none;fill:#000000;fill-opacity:1;stroke:none;stroke-width:1.41299295;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;paint-order:stroke fill markers"
|
||||
inkscape:connector-curvature="0" />
|
||||
<rect
|
||||
inkscape:transform-center-x="-27.960727"
|
||||
transform="rotate(60)"
|
||||
inkscape:transform-center-y="-16.143018"
|
||||
style="opacity:1;vector-effect:none;fill:url(#linearGradient2673-8);fill-opacity:1;stroke:none;stroke-width:1.41299284;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;paint-order:stroke fill markers"
|
||||
id="rect2623-2"
|
||||
width="7.575388"
|
||||
height="30.240459"
|
||||
x="204.99998"
|
||||
y="90.775146"
|
||||
rx="1.4310507"
|
||||
ry="1.4310507" />
|
||||
<path
|
||||
id="rect2779-1"
|
||||
d="m 25.629824,228.93732 c -0.1408,-0.005 -0.28501,0.01 -0.428601,0.0483 l -22.0494031,5.90826 -4.2151809,2.43348 c -0.6865843,0.3964 -0.9200029,1.2683 -0.5236086,1.95489 l 2.35648161,4.08178 c 0.00182,0.003 0.004124,0.006 0.005944,0.009 l 5.30053709,-1.42014 20.3587019,-11.7542 c 0.18213,-0.10516 0.331531,-0.24423 0.446603,-0.40396 -0.220815,-0.50756 -0.710664,-0.83658 -1.251449,-0.85744 z"
|
||||
style="opacity:0.072;vector-effect:none;fill:#000000;fill-opacity:1;stroke:none;stroke-width:1.41299295;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;paint-order:stroke fill markers"
|
||||
inkscape:connector-curvature="0" />
|
||||
<rect
|
||||
ry="1.4310507"
|
||||
rx="1.4310507"
|
||||
y="32.695652"
|
||||
x="228.58229"
|
||||
height="30.240459"
|
||||
width="7.575388"
|
||||
id="rect2625-0"
|
||||
style="opacity:1;vector-effect:none;fill:url(#linearGradient5678);fill-opacity:1;stroke:none;stroke-width:1.41299284;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;paint-order:stroke fill markers"
|
||||
inkscape:transform-center-y="-8.3562031"
|
||||
transform="rotate(75)"
|
||||
inkscape:transform-center-x="-31.186109" />
|
||||
<path
|
||||
id="rect2810-5"
|
||||
d="m 14.997144,233.2388 c 0,0 -1.018353,0.10729 -2.407435,0.81561 -1.013978,0.51705 -2.306717,1.63862 -3.1433504,1.86637 -3.1283181,0.85159 -9.69421033,0.79155 -9.69421033,0.79155 -0.76578557,0.20519 -1.21710747,0.98676 -1.01191707,1.75255 l 1.21993397,4.55279 c 0.20519045,0.76579 0.98677017,1.21711 1.75255573,1.01192 l 26.4455981,-7.08626 c 0.765786,-0.20519 1.217108,-0.98676 1.011917,-1.75255 l -0.591856,-2.2084 z"
|
||||
style="opacity:0.07099998;vector-effect:none;fill:#000000;fill-opacity:1;stroke:none;stroke-width:1.41299295;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;paint-order:stroke fill markers"
|
||||
inkscape:connector-curvature="0"
|
||||
sodipodi:nodetypes="csscccccccc" />
|
||||
</g>
|
||||
</g>
|
||||
<path
|
||||
style="opacity:0.66799999;vector-effect:none;fill:url(#linearGradient3096-8);fill-opacity:1;stroke:none;stroke-width:1.62901139;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;paint-order:stroke fill markers;filter:url(#filter3130-5)"
|
||||
d="m 1365.4604,94.01541 c -0.7804,0 -1.241,0.234791 -1.0325,0.526396 l 4.7725,6.674764 -3.582,0.3862 c -0.8145,0.0879 -1.363,0.36813 -1.4493,0.69362 -0.027,0.0194 -0.053,0.0388 -0.075,0.0593 -0.1454,0.13326 -0.1905,0.28935 -0.115,0.45823 0,0 2e-4,1.9e-4 2e-4,1.9e-4 0.013,0.0337 0.034,0.0681 0.06,0.10273 l 5.6074,7.84226 c 0.05,0.0694 0.1169,0.13701 0.1986,0.20238 0,0 2e-4,1.9e-4 2e-4,1.9e-4 0.1644,0.13066 0.3904,0.25203 0.6592,0.35859 0.2019,0.08 0.424,0.15162 0.6691,0.2128 0.5654,0.14275 1.2217,0.22825 1.8718,0.22825 h 35.4505 c 0.093,-10e-6 0.1828,-0.002 0.2714,-0.005 0.2636,-0.0102 0.5048,-0.0355 0.7186,-0.0734 0.071,-0.0126 0.1394,-0.0267 0.2044,-0.0421 0.065,-0.0153 0.1267,-0.0323 0.1852,-0.0502 0.117,-0.0359 0.2203,-0.077 0.3091,-0.12223 0.2664,-0.13583 0.4003,-0.31088 0.3673,-0.5069 -0.01,-0.0327 -0.016,-0.0659 -0.031,-0.0996 -0.013,-0.0338 -0.034,-0.068 -0.06,-0.10273 l -1.7115,-2.39388 -2.1839,-3.05449 -1.7117,-2.39389 c -0.025,-0.0347 -0.049,-0.0692 -0.087,-0.10292 -0.033,-0.0338 -0.071,-0.067 -0.1115,-0.0996 -0.1645,-0.13073 -0.3903,-0.25198 -0.6593,-0.35859 -0.1345,-0.0533 -0.2798,-0.10301 -0.4344,-0.1483 -0.1537,-0.0453 -0.3151,-0.0863 -0.4838,-0.12224 0,0 -5e-4,0 -5e-4,0 -0.085,-0.0179 -0.1699,-0.0346 -0.2563,-0.05 0,0 -6e-4,0 -6e-4,0 -0.087,-0.0154 -0.1754,-0.0295 -0.2642,-0.0421 0,0 -6e-4,0 -6e-4,0 -0.2676,-0.0379 -0.5445,-0.0631 -0.823,-0.0734 0,0 -5e-4,0 -5e-4,0 -0.091,-0.003 -0.1849,-0.005 -0.2776,-0.005 h -5e-4 -1.3436 l -0.4127,-0.28792 -1.2344,-0.8622 c -0.2629,-0.18344 -0.7316,-0.31729 -1.2196,-0.36786 0.1127,-0.15515 -0.014,-0.34839 -0.3868,-0.512876 l -3.3931,-1.501175 c -0.3716,-0.164436 -0.8912,-0.257825 -1.3664,-0.263004 0,-0.01412 -0.01,-0.02836 -0.011,-0.04268 8e-4,-0.0059 0,-0.01166 0,-0.01757 10e-5,-7.23e-4 10e-5,-0.0011 -0.01,-0.0019 -0.062,-0.153559 -0.3058,-0.313129 -0.7073,-0.431393 l -4.1571,-1.225809 c -0.4553,-0.13428 -0.9904,-0.180421 -1.4201,-0.139807 -0.01,-0.0087 -0.012,-0.01741 -0.018,-0.02608 -0.03,-0.0287 -0.06,-0.05691 -0.099,-0.08477 -0.01,-0.0071 -0.019,-0.01405 -0.029,-0.02104 -0.041,-0.02773 -0.086,-0.05499 -0.1391,-0.0811 -0.1806,-0.09206 -0.4333,-0.172313 -0.7282,-0.227476 l -4.6375,-0.866642 c -0.5082,-0.09498 -1.0223,-0.09104 -1.3778,-0.0073 -0.019,-0.0099 -0.031,-0.01951 -0.047,-0.02915 -0.042,-0.02496 -0.089,-0.04916 -0.1403,-0.07241 -0.012,-0.0039 -0.013,-0.0081 -0.024,-0.01196 -0.063,-0.02608 -0.1242,-0.0504 -0.1935,-0.07357 -0.052,-0.01835 -0.113,-0.03595 -0.1693,-0.05214 -3e-4,-3.74e-4 10e-5,-7.23e-4 2e-4,-0.0015 -0.1984,-0.0536 -0.4223,-0.09456 -0.6608,-0.116829 l -4.8017,-0.448769 c -0.5254,-0.04909 -0.9827,0.0045 -1.2396,0.125132 -0.01,-0.0026 -0.015,-0.0052 -0.023,-0.0079 -0.01,-0.0068 -0.037,-0.01312 -0.046,-0.01969 -0.059,-0.02074 -0.1157,-0.04038 -0.1681,-0.05871 -0.018,-0.0065 -0.046,-0.01255 -0.064,-0.01872 -0.056,-0.01555 -0.1122,-0.02975 -0.1713,-0.04306 -0.038,-0.0086 -0.076,-0.0173 -0.1133,-0.02492 -0.02,-0.0033 -0.033,-0.0065 -0.049,-0.0095 -0.07,-0.0127 -0.1414,-0.02354 -0.2141,-0.03284 -0.014,-0.0015 -0.025,-0.003 -0.036,-0.0045 -0.078,-0.0092 -0.1542,-0.01629 -0.2326,-0.02123 -3e-4,-1.83e-4 -0.012,-7.23e-4 -0.012,-7.23e-4 v 0 c 0,0 -5e-4,1.91e-4 -5e-4,1.91e-4 -0.08,-0.0048 -0.1603,-0.0079 -0.2406,-0.0079 z"
|
||||
id="rect2977-7"
|
||||
inkscape:connector-curvature="0"
|
||||
inkscape:transform-center-y="-7.3219625"
|
||||
inkscape:transform-center-x="3.5474848"
|
||||
transform="matrix(1.0159411,0,0,0.83457554,-1376.5639,194.42636)" />
|
||||
<path
|
||||
inkscape:connector-curvature="0"
|
||||
id="path5289"
|
||||
d="m 36.115727,260.49398 c -0.86895,0.59707 -1.34094,1.48038 -3.428115,2.87126 -0.380703,0.2537 -2.981025,0.21653 -3.746995,0.21176 h -10.91469 c -1.15136,0 -2.07801,0.92699 -2.07801,2.07833 v 20.76027 c 0,1.15135 0.92665,2.078 2.07801,2.078 h 36.06755 c 1.15135,0 2.07833,-0.92665 2.07833,-2.078 v -4.08201 -16.67826 -4.08201 c 0,-1.15135 -0.92698,-2.07832 -2.07833,-2.07832 H 39.945486 c -1.68704,0 -2.960809,0.40188 -3.829759,0.99898 z"
|
||||
style="opacity:1;fill:url(#linearGradient5315);fill-opacity:1;stroke:none;stroke-width:5.29166698;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;paint-order:markers fill stroke"
|
||||
sodipodi:nodetypes="zscssssssccsscz" />
|
||||
<path
|
||||
inkscape:connector-curvature="0"
|
||||
id="path5275-0"
|
||||
d="m 38.745599,266.74442 a 1.346382,1.346382 0 0 0 -1.32602,1.36425 v 9.59839 l -1.68724,-1.67484 a 1.346382,1.346382 0 0 0 -0.96686,-0.40462 1.346382,1.346382 0 0 0 -0.93018,2.31458 l 3.78272,3.75533 a 1.346382,1.346382 0 0 0 0.68885,0.53537 1.346382,1.346382 0 0 0 0.92087,-0.001 1.346382,1.346382 0 0 0 0.68678,-0.53537 l 3.7822,-3.75428 a 1.346382,1.346382 0 0 0 -0.96997,-2.31459 1.346382,1.346382 0 0 0 -0.92759,0.40463 l -1.68724,1.67535 v -9.5989 a 1.346382,1.346382 0 0 0 -1.36632,-1.36426 z m 9.32759,0 a 1.346382,1.346382 0 0 0 -0.43408,0.0806 1.346382,1.346382 0 0 0 -0.65009,0.4837 l -3.82612,3.79821 a 1.346405,1.346405 0 1 0 1.89704,1.911 l 1.68775,-1.67535 v 9.59786 a 1.346382,1.346382 0 1 0 2.69183,0 v -9.59786 l 1.68775,1.67535 a 1.3464068,1.3464068 0 1 0 1.89704,-1.911 l -3.82871,-3.80028 a 1.346382,1.346382 0 0 0 -0.59737,-0.46457 1.346382,1.346382 0 0 0 -0.52504,-0.0977 z"
|
||||
style="color:#000000;font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;font-size:medium;line-height:normal;font-family:sans-serif;font-variant-ligatures:normal;font-variant-position:normal;font-variant-caps:normal;font-variant-numeric:normal;font-variant-alternates:normal;font-feature-settings:normal;text-indent:0;text-align:start;text-decoration:none;text-decoration-line:none;text-decoration-style:solid;text-decoration-color:#000000;letter-spacing:normal;word-spacing:normal;text-transform:none;writing-mode:lr-tb;direction:ltr;text-orientation:mixed;dominant-baseline:auto;baseline-shift:baseline;text-anchor:start;white-space:normal;shape-padding:0;clip-rule:nonzero;display:inline;overflow:visible;visibility:visible;opacity:1;isolation:auto;mix-blend-mode:normal;color-interpolation:sRGB;color-interpolation-filters:linearRGB;solid-color:#000000;solid-opacity:1;vector-effect:none;fill:#ffffff;fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:5.29166651;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;paint-order:markers fill stroke;color-rendering:auto;image-rendering:auto;shape-rendering:auto;text-rendering:auto;enable-background:accumulate" />
|
||||
</g>
|
||||
</g>
|
||||
<rect
|
||||
style="opacity:0;vector-effect:none;fill:#ffffff;fill-opacity:1;stroke:none;stroke-width:1.5;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;paint-order:stroke fill markers"
|
||||
id="rect4254"
|
||||
width="67.733337"
|
||||
height="67.733337"
|
||||
x="-119.13585"
|
||||
y="205.91806"
|
||||
rx="1.3047903"
|
||||
ry="1.3047903" />
|
||||
</g>
|
||||
</svg>
|
After Width: | Height: | Size: 36 KiB |
21
extensions/fablabchemnitz/gradient_saver/meta.json
Normal file
21
extensions/fablabchemnitz/gradient_saver/meta.json
Normal file
@ -0,0 +1,21 @@
|
||||
[
|
||||
{
|
||||
"name": "Gradient Saver",
|
||||
"id": "fablabchemnitz.de.gradient_saver",
|
||||
"path": "gradient_saver",
|
||||
"dependent_extensions": null,
|
||||
"original_name": "Gradient Saver",
|
||||
"original_id": "id.artemtech.gradient_saver",
|
||||
"license": "GNU GPL v3",
|
||||
"license_url": "https://github.com/artemtech/inkscape-gradient-saver/blob/inkscape-1.0/LICENSE",
|
||||
"comment": "",
|
||||
"source_url": "https://gitea.fablabchemnitz.de/FabLab_Chemnitz/mightyscape-1.2/src/branch/master/extensions/fablabchemnitz/gradient_saver",
|
||||
"fork_url": "https://github.com/artemtech/inkscape-gradient-saver/",
|
||||
"documentation_url": "https://stadtfabrikanten.org/display/IFM/Gradient+Saver",
|
||||
"inkscape_gallery_url": null,
|
||||
"main_authors": [
|
||||
"github.com/artemtech",
|
||||
"github.com/eridur-de"
|
||||
]
|
||||
}
|
||||
]
|
@ -0,0 +1,47 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<inkscape-extension xmlns="http://www.inkscape.org/namespace/inkscape/extension">
|
||||
<name>Grey to MonoAlpha</name>
|
||||
<id>fablabchemnitz.de.grey_to_monoalpha</id>
|
||||
<param name="tab" type="notebook">
|
||||
<page name="main_page" gui-text="Settings">
|
||||
<vbox>
|
||||
<hbox>
|
||||
<param name="color_picker_mono" type="color" appearance="colorbutton" gui-text="Mono Color">0x000000ff</param>
|
||||
</hbox>
|
||||
<hbox>
|
||||
<param name="apply_to_type_radio" type="optiongroup" appearance="radio" gui-text="Apply To">
|
||||
<option value="fill_and_stroke">Fill and Stroke</option>
|
||||
<option value="fill">Fill Only</option>
|
||||
<option value="stroke">Stroke Only</option>
|
||||
</param>
|
||||
</hbox>
|
||||
<hbox>
|
||||
<label>Opacity Threshold</label>
|
||||
<param name="opacity_lower_threshold" type="float" min="0" max="0.9" gui-text="Lower" gui-description="opacity_lower_threshold">0</param>
|
||||
<param name="opacity_upper_threshold" type="float" min="0.05" max="1" gui-text="Upper" gui-description="opacity_upper_threshold">1</param>
|
||||
</hbox>
|
||||
</vbox>
|
||||
</page>
|
||||
<page name="about_page" gui-text="About">
|
||||
<label>Grey To MonoAlpha - An Inkscape Extension</label>
|
||||
<label>Inkscape 1.1 +</label>
|
||||
<label appearance="url">https://gitlab.com/inklinea/</label>
|
||||
<label xml:space="preserve">
|
||||
▶ Converts a greyscale image to monochrome with variable opacity
|
||||
▶ Threshold setting to avoid solid color
|
||||
▶ Can be applied to stroke, fill or both
|
||||
</label>
|
||||
</page>
|
||||
</param>
|
||||
<effect>
|
||||
<object-type>path</object-type>
|
||||
<effects-menu>
|
||||
<submenu name="FabLab Chemnitz">
|
||||
<submenu name="Colors/Gradients/Filters"/>
|
||||
</submenu>
|
||||
</effects-menu>
|
||||
</effect>
|
||||
<script>
|
||||
<command location="inx" interpreter="python">grey_to_monoalpha.py</command>
|
||||
</script>
|
||||
</inkscape-extension>
|
@ -0,0 +1,99 @@
|
||||
#!/usr/bin/env python3
|
||||
#
|
||||
# Copyright (C) [2021] [Matt Cottam], [mpcottam@raincloud.co.uk]
|
||||
#
|
||||
# This program is free software; you can redistribute it and/or modify
|
||||
# it under the terms of the GNU General Public License as published by
|
||||
# the Free Software Foundation; either version 2 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 General Public License for more details.
|
||||
#
|
||||
# You should have received a copy of the GNU General Public License
|
||||
# along with this program; if not, write to the Free Software
|
||||
# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
|
||||
#
|
||||
|
||||
##############################################################################
|
||||
# Grey To Mono Alpha *** Convert Greys to Monochrome with varying Opacity
|
||||
##############################################################################
|
||||
|
||||
import math
|
||||
|
||||
import inkex
|
||||
from inkex import Color
|
||||
|
||||
# Python Standard Libary
|
||||
|
||||
from statistics import mean
|
||||
|
||||
|
||||
def get_attributes(self):
|
||||
for att in dir(self):
|
||||
inkex.errormsg((att, getattr(self, att)))
|
||||
|
||||
|
||||
def rgba_to_bw_rgba(self, my_objects):
|
||||
apply_to = self.options.apply_to_type_radio
|
||||
mono_color = self.options.color_picker_mono.to_rgba()
|
||||
opacity_lower_threshold = self.options.opacity_lower_threshold
|
||||
opacity_upper_threshold = self.options.opacity_upper_threshold
|
||||
opacity_range = opacity_upper_threshold - opacity_lower_threshold
|
||||
|
||||
for my_object in my_objects:
|
||||
|
||||
if 'fill' in apply_to and ('fill:none' not in str(my_object.style)):
|
||||
my_fill_color = my_object.style.get_color(name='fill').to_rgba()
|
||||
my_fill_color_red = my_fill_color[0]
|
||||
my_fill_color_green = my_fill_color[1]
|
||||
my_fill_color_blue = my_fill_color[2]
|
||||
mean_fill_component_value = mean([my_fill_color_red, my_fill_color_blue, my_fill_color_green])
|
||||
|
||||
if mean_fill_component_value > 0:
|
||||
mono_opacity = (1 - (mean_fill_component_value / 256)) * opacity_range
|
||||
mono_opacity = mono_opacity + opacity_lower_threshold
|
||||
else:
|
||||
mono_opacity = opacity_upper_threshold
|
||||
|
||||
my_object.style['fill'] = str(mono_color)
|
||||
my_object.style['fill-opacity'] = str(mono_opacity)
|
||||
|
||||
if 'stroke' in apply_to and (';stroke:none' not in str(my_object.style)) and ('stroke:' in str(my_object.style)):
|
||||
my_stroke_color = my_object.style.get_color(name='stroke').to_rgba()
|
||||
my_stroke_color_red = my_stroke_color[0]
|
||||
my_stroke_color_green = my_stroke_color[1]
|
||||
my_stroke_color_blue = my_stroke_color[2]
|
||||
mean_stroke_component_value = mean([my_stroke_color_red, my_stroke_color_blue, my_stroke_color_green])
|
||||
|
||||
if mean_stroke_component_value > 0:
|
||||
mono_opacity = (1 - (mean_stroke_component_value / 256)) * opacity_range
|
||||
mono_opacity = mono_opacity + opacity_lower_threshold
|
||||
else:
|
||||
mono_opacity = opacity_upper_threshold
|
||||
|
||||
my_object.style['stroke'] = str(mono_color)
|
||||
my_object.style['stroke-opacity'] = str(mono_opacity)
|
||||
|
||||
|
||||
class GreyToMonoAlpha(inkex.EffectExtension):
|
||||
|
||||
def add_arguments(self, pars):
|
||||
pars.add_argument("--tab")
|
||||
pars.add_argument("--color_picker_mono", type=inkex.colors.Color, default=0)
|
||||
pars.add_argument("--apply_to_type_radio", default=None)
|
||||
pars.add_argument("--opacity_lower_threshold", type=float, default=0)
|
||||
pars.add_argument("--opacity_upper_threshold", type=float, default=1)
|
||||
|
||||
def effect(self):
|
||||
my_objects = self.svg.selected
|
||||
if len(my_objects) < 1:
|
||||
self.msg('Please select some paths first.')
|
||||
return
|
||||
rgba_to_bw_rgba(self, my_objects)
|
||||
|
||||
|
||||
if __name__ == '__main__':
|
||||
GreyToMonoAlpha().run()
|
21
extensions/fablabchemnitz/grey_to_monoalpha/meta.json
Normal file
21
extensions/fablabchemnitz/grey_to_monoalpha/meta.json
Normal file
@ -0,0 +1,21 @@
|
||||
[
|
||||
{
|
||||
"name": "Grey To MonoAlpha",
|
||||
"id": "fablabchemnitz.de.grey_to_monoalpha",
|
||||
"path": "grey_to_monoalpha",
|
||||
"dependent_extensions": null,
|
||||
"original_name": "Grey to MonoAlpha",
|
||||
"original_id": "org.inkscape.grey_to_monoalpha",
|
||||
"license": "GNU GPL v3",
|
||||
"license_url": "https://gitlab.com/inklinea/grey-to-mono-alpha/-/blob/main/LICENSE",
|
||||
"comment": "",
|
||||
"source_url": "https://gitea.fablabchemnitz.de/FabLab_Chemnitz/mightyscape-1.2/src/branch/master/extensions/fablabchemnitz/grey_to_monoalpha",
|
||||
"fork_url": "https://gitlab.com/inklinea/grey-to-mono-alpha",
|
||||
"documentation_url": "https://stadtfabrikanten.org/display/IFM/Grey+to+MonoAlpha",
|
||||
"inkscape_gallery_url": null,
|
||||
"main_authors": [
|
||||
"gitlab.com/inklinea",
|
||||
"github.com/eridur-de"
|
||||
]
|
||||
}
|
||||
]
|
@ -9,13 +9,13 @@
|
||||
"license": "GNU GPL v2",
|
||||
"license_url": "https://github.com/nicolaromano/triangulate/blob/master/triangulation.py",
|
||||
"comment": "",
|
||||
"source_url": "https://gitea.fablabchemnitz.de/FabLab_Chemnitz/mightyscape-1.X/src/branch/master/extensions/fablabchemnitz/image_triangulation",
|
||||
"source_url": "https://gitea.fablabchemnitz.de/FabLab_Chemnitz/mightyscape-1.2/src/branch/master/extensions/fablabchemnitz/image_triangulation",
|
||||
"fork_url": "https://github.com/nicolaromano/triangulate",
|
||||
"documentation_url": "https://stadtfabrikanten.org/display/IFM/Image+Triangulation",
|
||||
"inkscape_gallery_url": null,
|
||||
"main_authors": [
|
||||
"github.com/nicolaromano",
|
||||
"github.com/vmario89"
|
||||
"github.com/eridur-de"
|
||||
]
|
||||
}
|
||||
]
|
@ -9,13 +9,13 @@
|
||||
"license": "GNU GPL v2",
|
||||
"license_url": "https://sourceforge.net/p/razorfoss/svn/HEAD/tree/trunk/Inkscape/InsetAlignmentExtension/InsetAlignment.py",
|
||||
"comment": "",
|
||||
"source_url": "https://gitea.fablabchemnitz.de/FabLab_Chemnitz/mightyscape-1.X/src/branch/master/extensions/fablabchemnitz/inset_alignment",
|
||||
"source_url": "https://gitea.fablabchemnitz.de/FabLab_Chemnitz/mightyscape-1.2/src/branch/master/extensions/fablabchemnitz/inset_alignment",
|
||||
"fork_url": "https://sourceforge.net/p/razorfoss/svn/HEAD/tree/trunk/Inkscape/InsetAlignmentExtension/",
|
||||
"documentation_url": "https://stadtfabrikanten.org/display/IFM/Inset+Alignment",
|
||||
"inkscape_gallery_url": null,
|
||||
"main_authors": [
|
||||
"Luke Phillips:lukerazor@hotmail.com",
|
||||
"github.com/vmario89"
|
||||
"github.com/eridur-de"
|
||||
]
|
||||
}
|
||||
]
|
||||
|
17
extensions/fablabchemnitz/my-gradients.svg
Normal file
17
extensions/fablabchemnitz/my-gradients.svg
Normal file
@ -0,0 +1,17 @@
|
||||
<?xml version='1.0' encoding='utf-8'?>
|
||||
<svg xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd" xmlns:cc="http://creativecommons.org/ns#" xmlns:ccOLD="http://web.resource.org/cc/" xmlns:svg="http://www.w3.org/2000/svg" xmlns:dc="http://purl.org/dc/elements/1.1/" xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#" xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape" xmlns:xlink="http://www.w3.org/1999/xlink">
|
||||
<defs>
|
||||
<linearGradient id="test">
|
||||
<stop id="stop00" offset="0.0" style="stop-color:#cc20c1;stop-opacity:1.0"/>
|
||||
<stop id="stop01" offset="1.0" style="stop-color:#cc20c1;stop-opacity:0.0"/>
|
||||
</linearGradient>
|
||||
<linearGradient id="test">
|
||||
<stop id="stop10" offset="0.0" style="stop-color:#cc20c1;stop-opacity:1.0"/>
|
||||
<stop id="stop11" offset="1.0" style="stop-color:#cc20c1;stop-opacity:0.0"/>
|
||||
</linearGradient>
|
||||
<linearGradient id="test">
|
||||
<stop id="stop20" offset="0.0" style="stop-color:#cc20c1;stop-opacity:1.0"/>
|
||||
<stop id="stop21" offset="1.0" style="stop-color:#cc20c1;stop-opacity:0.0"/>
|
||||
</linearGradient>
|
||||
</defs>
|
||||
</svg>
|
After Width: | Height: | Size: 1.1 KiB |
21
extensions/fablabchemnitz/output_pro/meta.json
Normal file
21
extensions/fablabchemnitz/output_pro/meta.json
Normal file
@ -0,0 +1,21 @@
|
||||
[
|
||||
{
|
||||
"name": "Inkscape Output Pro",
|
||||
"id": "fablabchemnitz.de.output_pro",
|
||||
"path": "output_pro",
|
||||
"dependent_extensions": null,
|
||||
"original_name": "Inkscape Output Pro",
|
||||
"original_id": "org.inkscape.outputpro",
|
||||
"license": "GNU GPL v2",
|
||||
"license_url": "https://github.com/jonata/Inkscape-OUTPUT-PRO/blob/master/LICENSE.txt",
|
||||
"comment": "ported to Inkscape v1 by Mario Voigt",
|
||||
"source_url": "https://gitea.fablabchemnitz.de/FabLab_Chemnitz/mightyscape-1.2/src/branch/master/extensions/fablabchemnitz/output_pro",
|
||||
"fork_url": "https://github.com/jonata/Inkscape-OUTPUT-PRO",
|
||||
"documentation_url": "https://stadtfabrikanten.org/display/IFM/Output+Pro+for+Inkscape",
|
||||
"inkscape_gallery_url": null,
|
||||
"main_authors": [
|
||||
"github.com/jonata",
|
||||
"github.com/eridur-de"
|
||||
]
|
||||
}
|
||||
]
|
16
extensions/fablabchemnitz/output_pro/output_pro.inx
Normal file
16
extensions/fablabchemnitz/output_pro/output_pro.inx
Normal file
@ -0,0 +1,16 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<inkscape-extension xmlns="http://www.inkscape.org/namespace/inkscape/extension">
|
||||
<name>Inkscape Output Pro</name>
|
||||
<id>fablabchemnitz.de.output_pro</id>
|
||||
<effect>
|
||||
<object-type>all</object-type>
|
||||
<effects-menu>
|
||||
<submenu name="FabLab Chemnitz">
|
||||
<submenu name="Import/Export/Transfer"/>
|
||||
</submenu>
|
||||
</effects-menu>
|
||||
</effect>
|
||||
<script>
|
||||
<command location="inx" interpreter="python">output_pro.py</command>
|
||||
</script>
|
||||
</inkscape-extension>
|
1091
extensions/fablabchemnitz/output_pro/output_pro.py
Normal file
1091
extensions/fablabchemnitz/output_pro/output_pro.py
Normal file
File diff suppressed because it is too large
Load Diff
BIN
extensions/fablabchemnitz/output_pro/outputpro/alpha.png
Normal file
BIN
extensions/fablabchemnitz/output_pro/outputpro/alpha.png
Normal file
Binary file not shown.
After Width: | Height: | Size: 170 B |
118
extensions/fablabchemnitz/output_pro/outputpro/cmyk.py
Normal file
118
extensions/fablabchemnitz/output_pro/outputpro/cmyk.py
Normal file
@ -0,0 +1,118 @@
|
||||
#!/usr/bin/env python3
|
||||
|
||||
import re
|
||||
import os
|
||||
import inkex
|
||||
from inkex.command import inkscape
|
||||
|
||||
def calculateCMYK(red, green, blue):
|
||||
C = float()
|
||||
M = float()
|
||||
Y = float()
|
||||
K = float()
|
||||
|
||||
if 1.00 - red < 1.00 - green:
|
||||
K = 1.00 - red
|
||||
else:
|
||||
K = 1.00 - green
|
||||
|
||||
if 1.00 - blue < K:
|
||||
K = 1.00 - blue
|
||||
|
||||
if K != 1.00:
|
||||
C = ( 1.00 - red - K ) / ( 1.00 - K )
|
||||
M = ( 1.00 - green - K ) / ( 1.00 - K )
|
||||
Y = ( 1.00 - blue - K ) / ( 1.00 - K )
|
||||
|
||||
return [C, M, Y, K]
|
||||
|
||||
def clean_svg_color_definitions(svg):
|
||||
def change_colors(origin, color_type):
|
||||
for i in range(len(str(origin).split(color_type + ':'))):
|
||||
if str(str(origin).split(color_type + ':')[i].split(';')[0]) in inkex.colors.SVG_COLOR.keys():
|
||||
color_numbers = str(inkex.Color(inkex.Color(str(str(origin).split(color_type + ':')[i].split(';')[0])).to_rgb()))
|
||||
origin = str(origin).replace(':' + str(str(origin).split(color_type + ':')[i].split(';')[0]) + ';', ':' + color_numbers + ';')
|
||||
return origin
|
||||
|
||||
colortypes = ['fill', 'stop-color', 'flood-color', 'lighting-color', 'stroke']
|
||||
for i in range(len(colortypes)):
|
||||
svg = change_colors(svg, colortypes[i])
|
||||
|
||||
return svg
|
||||
|
||||
def removeK(origin):
|
||||
def reset_opacity(value):
|
||||
return str(value.group()).split('opacity:')[0] + "opacity:0;"
|
||||
#return re.sub("#000000;fill-opacity:[0-9.]+;", reset_opacity, re.sub("#000000;stop-opacity:[0-9.]+;", reset_opacity, re.sub("#000000;stroke-opacity:[0-9.]+;", reset_opacity, re.sub("#000000;flood-opacity:[0-9.]+;", reset_opacity, re.sub("#000000;lighting-opacity:[0-9.]+;", reset_opacity, origin)))))
|
||||
return re.sub("#000000;fill-opacity:[0-9.?]+", reset_opacity, re.sub("#000000;stop-opacity:[0-9.?]+", reset_opacity, re.sub("#000000;stroke-opacity:[0-9.?]+", reset_opacity, re.sub("#000000;flood-opacity:[0-9.?]+", reset_opacity, re.sub("#000000;lighting-opacity:[0-9.?]+", reset_opacity, origin)))))
|
||||
|
||||
def representC(value):
|
||||
# returns CMS color if available
|
||||
if (re.search("icc-color", value.group())):
|
||||
return str(inkex.Color((float(1.00 - float(re.split(r'[,\)\s]+',value.group())[2])), float(1.00), float(1.00))))
|
||||
else:
|
||||
red = float(inkex.Color(str(value.group())).to_rgb()[0]/255.00)
|
||||
green = float(inkex.Color(str(value.group())).to_rgb()[1]/255.00)
|
||||
blue = float(inkex.Color(str(value.group())).to_rgb()[2]/255.00)
|
||||
return str(inkex.Color((float(1.00 - calculateCMYK(red, green, blue)[0]), float(1.00), float(1.00))))
|
||||
|
||||
def representM(value):
|
||||
# returns CMS color if available
|
||||
if ( re.search("icc-color", value.group()) ):
|
||||
return str(inkex.Color((float(1.00), float(1.00 - float(re.split(r'[,\)\s]+',value.group())[3])), float(1.00))))
|
||||
else:
|
||||
red = float(inkex.Color(str(value.group())).to_rgb()[0]/255.00)
|
||||
green = float(inkex.Color(str(value.group())).to_rgb()[1]/255.00)
|
||||
blue = float(inkex.Color(str(value.group())).to_rgb()[2]/255.00)
|
||||
return str(inkex.Color((float(1.00), float(1.00 - calculateCMYK(red, green, blue)[1]), float(1.00))))
|
||||
|
||||
def representY(value):
|
||||
# returns CMS color if available
|
||||
if (re.search("icc-color", value.group()) ):
|
||||
return str(inkex.Color((float(1.00), float(1.00), float(1.00 - float(re.split(r'[,\)\s]+',value.group())[4])))))
|
||||
else:
|
||||
red = float(inkex.Color(str(value.group())).to_rgb()[0]/255.00)
|
||||
green = float(inkex.Color(str(value.group())).to_rgb()[1]/255.00)
|
||||
blue = float(inkex.Color(str(value.group())).to_rgb()[2]/255.00)
|
||||
return str(inkex.Color((float(1.00), float(1.00), float(1.00 - calculateCMYK(red, green, blue)[2]))))
|
||||
|
||||
def representK(value):
|
||||
# returns CMS color if available
|
||||
if (re.search("icc-color", value.group()) ):
|
||||
return str(inkex.Color((float(1.00 - float(re.split(r'[,\)\s]+',value.group())[5])), float(1.00 - float(re.split(r'[,\)\s]+',value.group())[5])), float(1.00 - float(re.split(r'[,\)\s]+',value.group())[5])))))
|
||||
else:
|
||||
red = float(inkex.Color(str(value.group())).to_rgb()[0]/255.00)
|
||||
green = float(inkex.Color(str(value.group())).to_rgb()[1]/255.00)
|
||||
blue = float(inkex.Color(str(value.group())).to_rgb()[2]/255.00)
|
||||
return str(inkex.Color((float(1.00 - calculateCMYK(red, green, blue)[3]), float(1.00 - calculateCMYK(red, green, blue)[3]), float(1.00 - calculateCMYK(red, green, blue)[3]))))
|
||||
|
||||
|
||||
def generate_svg_separations(temp_dir, original_source, overblack):
|
||||
svg_ready = clean_svg_color_definitions(original_source)
|
||||
|
||||
with open(os.path.join(temp_dir, "separationK.svg"), "w") as f:
|
||||
f.write(re.sub(r"#[a-fA-F0-9]{6}( icc-color\(.*?\))?", representK, svg_ready))
|
||||
|
||||
if overblack:
|
||||
svg_ready = removeK(svg_ready)
|
||||
|
||||
with open(os.path.join(temp_dir, "separationC.svg"), "w") as f:
|
||||
f.write(re.sub(r"#[a-fA-F0-9]{6}( icc-color\(.*?\))?", representC, svg_ready))
|
||||
with open(os.path.join(temp_dir, "separationM.svg"), "w") as f:
|
||||
f.write(re.sub(r"#[a-fA-F0-9]{6}( icc-color\(.*?\))?", representM, svg_ready))
|
||||
with open(os.path.join(temp_dir, "separationY.svg"), "w") as f:
|
||||
f.write(re.sub(r"#[a-fA-F0-9]{6}( icc-color\(.*?\))?", representY, svg_ready))
|
||||
|
||||
def generate_png_separations(temp_dir, area_to_export, resolution, alpha):
|
||||
if alpha:
|
||||
alpha_command = ""
|
||||
else:
|
||||
alpha_command = ";export-background:white"
|
||||
for color in ['C', 'M', 'Y', 'K']:
|
||||
cmd = area_to_export + alpha_command + ';export-dpi:' + str(resolution) + ';export-background-opacity:1;export-filename:' + os.path.join(temp_dir, "separated" + area_to_export.replace(' ', '') + color + ".png") + ';export-do'
|
||||
#inkex.utils.debug(cmd)
|
||||
cli_output = inkscape(os.path.join(temp_dir, "separation" + color + ".svg"), actions=cmd)
|
||||
if len(cli_output) > 0:
|
||||
inkex.utils.debug(cli_output)
|
||||
#inkex.utils.debug(os.listdir(temp_dir))
|
||||
|
84
extensions/fablabchemnitz/output_pro/outputpro/cutmarks.py
Normal file
84
extensions/fablabchemnitz/output_pro/outputpro/cutmarks.py
Normal file
@ -0,0 +1,84 @@
|
||||
#!/usr/bin/env python3
|
||||
|
||||
import subprocess
|
||||
import os
|
||||
|
||||
def generate_final_file(isvector, hide_inside_marks, colormode, width, height, space, strokewidth, bleedsize, marksize, temp_dir):
|
||||
if not isvector:
|
||||
|
||||
if "nt" in os.name:
|
||||
shell = True
|
||||
else:
|
||||
shell = False
|
||||
|
||||
command = []
|
||||
final_command = ['convert']
|
||||
|
||||
for color in colormode:
|
||||
command.append('convert')
|
||||
command.append('-size')
|
||||
command.append(str(sum(width) + (marksize*2) + (space * (len(width) -1))) + 'x' + str(sum(height) + (marksize*2) + (space * (len(height) -1))))
|
||||
command.append('xc:white')
|
||||
command.append('-stroke')
|
||||
command.append('black')
|
||||
command.append('-strokewidth')
|
||||
command.append(str(strokewidth))
|
||||
|
||||
width_value = 0
|
||||
number_of_column = 1
|
||||
|
||||
for column in width:
|
||||
height_value = 0
|
||||
number_of_line = 1
|
||||
|
||||
for line in height:
|
||||
with open(os.path.join(temp_dir, 'str.txt'), 'a') as f:
|
||||
f.write(str(width.index(column)))
|
||||
|
||||
if not hide_inside_marks or (hide_inside_marks and number_of_column == 1):
|
||||
command.append('-draw')
|
||||
command.append('line ' + str(width_value + marksize) + ',' + str(height_value + marksize + bleedsize) + ', ' + str(width_value) + ',' + str(height_value + marksize + bleedsize))
|
||||
command.append('-draw')
|
||||
command.append('line ' + str(width_value + marksize) + ',' + str(height_value + line + marksize - bleedsize) + ', ' + str(width_value) + ',' + str(height_value + line + marksize - bleedsize))
|
||||
|
||||
if not hide_inside_marks or (hide_inside_marks and number_of_line == 1):
|
||||
command.append('-draw')
|
||||
command.append('line ' + str(width_value + marksize + bleedsize) + ',' + str(height_value + marksize) + ', ' + str(width_value + marksize + bleedsize) + ',' + str(height_value))
|
||||
command.append('-draw')
|
||||
command.append('line ' + str(width_value + column + marksize - bleedsize) + ',' + str(height_value + marksize) + ', ' + str(width_value + column + marksize - bleedsize) + ',' + str(height_value))
|
||||
|
||||
if not hide_inside_marks or (hide_inside_marks and number_of_column == len(width)):
|
||||
command.append('-draw')
|
||||
command.append('line ' + str(width_value + marksize + column) + ',' + str(height_value + marksize + bleedsize) + ', ' + str(width_value + (marksize*2) + column) + ',' + str(height_value + marksize + bleedsize))
|
||||
command.append('-draw')
|
||||
command.append('line ' + str(width_value + marksize + column) + ',' + str(height_value + line + marksize - bleedsize) + ', ' + str(width_value + (marksize*2) + column) + ',' + str(height_value + marksize + line - bleedsize))
|
||||
|
||||
if not hide_inside_marks or (hide_inside_marks and number_of_line == len(height)):
|
||||
command.append('-draw')
|
||||
command.append('line ' + str(width_value + marksize + bleedsize) + ',' + str(height_value + line + marksize) + ', ' + str(width_value + marksize + bleedsize) + ',' + str(height_value + line + (marksize*2)))
|
||||
command.append('-draw')
|
||||
command.append('line ' + str(width_value + column + marksize - bleedsize) + ',' + str(height_value + line + marksize) + ', ' + str(width_value + marksize + column - bleedsize) + ',' + str(height_value + line + (marksize*2)))
|
||||
|
||||
height_value += line + space
|
||||
number_of_line += 1
|
||||
width_value += column + space
|
||||
number_of_column += 1
|
||||
command.append(os.path.join(temp_dir, 'cut_mark_' + color + '.png'))
|
||||
subprocess.Popen(command, shell=shell).wait()
|
||||
del command[:]
|
||||
|
||||
command.append('convert')
|
||||
command.append(os.path.join(temp_dir, 'cut_mark_' + color + '.png'))
|
||||
command.append('-colorspace')
|
||||
command.append(str(colormode).lower())
|
||||
command.append('-channel')
|
||||
command.append('K')
|
||||
command.append('-separate')
|
||||
command.append(os.path.join(temp_dir, 'cut_mark_' + color + '.png'))
|
||||
subprocess.Popen(command, shell=shell).wait()
|
||||
del command[:]
|
||||
|
||||
final_command.append(os.path.join(temp_dir, 'cut_mark_' + color + '.png'))
|
||||
|
||||
final_command.extend(['-set', 'colorspace', colormode, '-combine', os.path.join(temp_dir, 'cut_mark.tiff')])
|
||||
subprocess.Popen(final_command, shell=shell).wait()
|
BIN
extensions/fablabchemnitz/output_pro/outputpro/preview_mask.png
Normal file
BIN
extensions/fablabchemnitz/output_pro/outputpro/preview_mask.png
Normal file
Binary file not shown.
After Width: | Height: | Size: 2.0 KiB |
BIN
extensions/fablabchemnitz/output_pro/outputpro/top.png
Normal file
BIN
extensions/fablabchemnitz/output_pro/outputpro/top.png
Normal file
Binary file not shown.
After Width: | Height: | Size: 69 KiB |
BIN
extensions/fablabchemnitz/output_pro/result-imp.jpeg
Normal file
BIN
extensions/fablabchemnitz/output_pro/result-imp.jpeg
Normal file
Binary file not shown.
After Width: | Height: | Size: 317 KiB |
22
extensions/fablabchemnitz/paths_to_openscad/meta.json
Normal file
22
extensions/fablabchemnitz/paths_to_openscad/meta.json
Normal file
@ -0,0 +1,22 @@
|
||||
[
|
||||
{
|
||||
"name": "Paths To OpenSCAD",
|
||||
"id": "fablabchemnitz.de.paths_to_openscad",
|
||||
"path": "paths_to_openscad",
|
||||
"dependent_extensions": null,
|
||||
"original_name": "aths to OpenSCAD<",
|
||||
"original_id": "command.extrude.openscad",
|
||||
"license": "GNU GPL v2",
|
||||
"license_url": "https://github.com/fablabnbg/inkscape-paths2openscad/blob/master/LICENSE",
|
||||
"comment": "",
|
||||
"source_url": "https://gitea.fablabchemnitz.de/FabLab_Chemnitz/mightyscape-1.2/src/branch/master/extensions/fablabchemnitz/paths_to_openscad",
|
||||
"fork_url": "https://github.com/fablabnbg/inkscape-paths2openscad",
|
||||
"documentation_url": "https://stadtfabrikanten.org/display/IFM/Paths+to+OpenSCAD",
|
||||
"inkscape_gallery_url": null,
|
||||
"main_authors": [
|
||||
"github.com/l0b0",
|
||||
"github.com/fablabnbg",
|
||||
"github.com/eridur-de"
|
||||
]
|
||||
}
|
||||
]
|
@ -0,0 +1,95 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<inkscape-extension xmlns="http://www.inkscape.org/namespace/inkscape/extension">
|
||||
<name>Paths To OpenSCAD</name>
|
||||
<id>fablabchemnitz.de.paths_to_openscad</id>
|
||||
<param name="tab" type="notebook">
|
||||
<page name="splash" gui-text="Paths to OpenSCAD">
|
||||
<param type="path" name="fname" gui-text="Output file" mode="file_new" filetypes="scad" gui-description="Use '{NAME}.scad' here to use the name from svg.">{NAME}.scad</param>
|
||||
<param name="zsize" type="float" min="0" max="1000" precision="2" gui-text="Depth (Z) [mm]" gui-description="Default 3D extrude depth (when no zsize is parsed from an svg object).">5.0</param>
|
||||
<param name="parsedesc" type="bool" gui-text="Description parsing" gui-description="Read the extruded zsize, zoffset, scale per svg object from its description or ID. See the Extrusion Syntax tab for details.">true</param>
|
||||
<param name="scadview" type="bool" gui-text="View in OpenSCAD" gui-description="Start OpenSCAD to view the 3D-model.">false</param>
|
||||
<param name="scad2stl" type="bool" gui-text="Convert to STL" gui-description="Also save an .stl file next to the specified output file.">false</param>
|
||||
<param name="stlpost" type="bool" gui-text="STL post processing" gui-description="Start e.g. a slicer after converting to STL. See the Commands tab for details.">false</param>
|
||||
<param name="stlmodule" type="bool" gui-text="Only create a module">false</param>
|
||||
</page>
|
||||
<page name="tuning" gui-text="Tuning">
|
||||
<param name="smoothness" type="float" min="0.0001" max="5" precision="4" gui-text="Smoothing" gui-description="Used when rendering curves. Smaller values are smoother. Range: 0.0001 to 5">0.2</param>
|
||||
<param type="float" name="chamfer" min="0.0" gui-text="Add chamfer radius [mm]">0</param>
|
||||
<param name="chamfer_fn" type="optiongroup" appearance="combo" gui-text="Chamfer precision ($fn)">
|
||||
<option value="4">4: Rough (fast)</option>
|
||||
<option value="12">12: Medium (slow)</option>
|
||||
<option value="16">16: Fine (slower)</option>
|
||||
<option value="32">32: Perfekt (slowest)</option>
|
||||
</param>
|
||||
<label appearance="header">Outline Mode</label>
|
||||
<label>Objects are extruded into 3D either in normal mode, or in outline mode. Normally filled areas are extruded, ignoring the line width. Objects with no fill are rendered in outline mode. Note: the 'Scale: XX %' instruction has no effect in outline mode.</label>
|
||||
<param name="min_line_width" type="float" min="0.1" max="10" gui-text="Minimum line width [mm]">1.0</param>
|
||||
<param type="float" name="line_width_scale_perc" min="1" max="10000" gui-text="Scale line width [%]">100.0</param>
|
||||
<param name="line_fn" type="optiongroup" appearance="combo" gui-text="Line width precision ($fn)">
|
||||
<option value="4">4: Rough (fast)</option>
|
||||
<option value="8">8: Medium (slow)</option>
|
||||
<option value="16">16: Fine (slower)</option>
|
||||
<option value="32">32: Perfekt (slowest)</option>
|
||||
</param>
|
||||
<param name="force_line" type="bool" gui-text="Force outline mode, ignore fill">false</param>
|
||||
<spacer/>
|
||||
</page>
|
||||
<page name="commands" gui-text="Commands">
|
||||
<label>Placeholders: You can use "{NAME}.scad" for the OpenSCAD file to read as specified as 'Output file' in the main tab. You can use "{NAME}.stl" for an STL file to write.</label>
|
||||
<param name="scadviewcmd" type="string" gui-text="View in OpenSCAD:" gui-description="Is only started, if no command of the same name is running. Always started non-blocking. A running OpenSCAD automatically picks up changed file content">openscad "{NAME}.scad"</param>
|
||||
<param name="scad2stlcmd" type="string" gui-text="Convert to STL:" gui-description="Automatically run, when STL postprocessing is requested.">openscad "{NAME}.scad" -o "{NAME}.stl"</param>
|
||||
<param name="stlpostcmd" type="string" gui-text="STL postprocessing:" gui-description="Append an '&' for non-blocking.">cura "{NAME}.stl" &</param>
|
||||
</page>
|
||||
<page name="extrusion" gui-text="Extrusion Syntax">
|
||||
<label xml:space="preserve">The depth (Z-Axis) and other parameters can be defined through an svg object's description. The menu 'Object->Object Properties ...' (Shift-Ctrl-O) shows details of one selected object.
|
||||
|
||||
If an object's ID is in either name_XXX_mm or name_XXXmm
|
||||
format, then XXX is translated into zsize in millimeters.
|
||||
Use . or _ as separator for a decimal number.
|
||||
Note that all whitespace or comma are saved as '_' in ID.
|
||||
</label>
|
||||
<label appearance="header">Syntax for the object property description</label>
|
||||
<label xml:space="preserve">Depth: 10 mm
|
||||
Linear extrusion length (or Z-Size)) of the object.
|
||||
|
||||
Antimatter: true
|
||||
Object is part of the difference set, which is
|
||||
cut away from all other objects.
|
||||
|
||||
Offset: 4.5 mm
|
||||
Move an object upwards to create a balcony (or window).
|
||||
|
||||
Taper: 90 % or Taper: 120,60 %
|
||||
Scale the object along its Z-axis. The bottom surface always
|
||||
is as drawn, but the top surface is scaled to this value.
|
||||
If two values are given (separated by Komma), different
|
||||
scaling applies along X- and Y-axis.
|
||||
|
||||
Parameters in the objects take precedence over groups.</label>
|
||||
</page>
|
||||
<page name="info" gui-text="About ...">
|
||||
<label xml:space="preserve">
|
||||
This extension converts Inkscape paths to extruded polygons in OpenSCAD. Before using, some objects must firat be converted to paths with the "Path > Object to Path" menu item.
|
||||
|
||||
Inkscape's units of pixels are converted to millimeters using the SVG standard's definition of 96 px = 1 inch = 25.4 mm. (Before inkscape 0.92 the standard was 90 px per inch, Adobe products often use 75 px per inch)
|
||||
|
||||
Dan Newman (dan newman @ mtbaldy us)
|
||||
Josef Skladanka (jskladan @ redhat com)
|
||||
Juergen Weigert (juergen @ fabmail org)
|
||||
|
||||
Find updates at</label>
|
||||
<label appearance="url">https://github.com/fablabnbg/inkscape-paths2openscad/releases</label>
|
||||
</page>
|
||||
</param>
|
||||
<effect needs-live-preview="false">
|
||||
<object-type>all</object-type>
|
||||
<effects-menu>
|
||||
<submenu name="FabLab Chemnitz">
|
||||
<submenu name="Import/Export/Transfer"/>
|
||||
</submenu>
|
||||
</effects-menu>
|
||||
</effect>
|
||||
<script>
|
||||
<command location="inx" interpreter="python">paths_to_openscad.py</command>
|
||||
</script>
|
||||
</inkscape-extension>
|
1487
extensions/fablabchemnitz/paths_to_openscad/paths_to_openscad.py
Normal file
1487
extensions/fablabchemnitz/paths_to_openscad/paths_to_openscad.py
Normal file
File diff suppressed because it is too large
Load Diff
@ -9,13 +9,13 @@
|
||||
"license": "GNU GPL v3",
|
||||
"license_url": "https://inkscape.org/~pakin/%E2%98%85pixels-to-objects",
|
||||
"comment": "",
|
||||
"source_url": "https://gitea.fablabchemnitz.de/FabLab_Chemnitz/mightyscape-1.X/src/branch/master/extensions/fablabchemnitz/pixels2objects",
|
||||
"source_url": "https://gitea.fablabchemnitz.de/FabLab_Chemnitz/mightyscape-1.2/src/branch/master/extensions/fablabchemnitz/pixels2objects",
|
||||
"fork_url": "https://inkscape.org/~pakin/%E2%98%85pixels-to-objects",
|
||||
"documentation_url": "https://stadtfabrikanten.org/display/IFM/Pixels+To+Objects",
|
||||
"inkscape_gallery_url": null,
|
||||
"main_authors": [
|
||||
"inkscape.org/pakin",
|
||||
"github.com/vmario89"
|
||||
"github.com/eridur-de"
|
||||
]
|
||||
}
|
||||
]
|
@ -7,14 +7,14 @@
|
||||
"original_name": "Primitive (Michael Fogleman)",
|
||||
"original_id": "fablabchemnitz.de.primitive",
|
||||
"license": "GNU GPL v3",
|
||||
"license_url": "https://gitea.fablabchemnitz.de/FabLab_Chemnitz/mightyscape-1.X/src/branch/master/LICENSE",
|
||||
"license_url": "https://gitea.fablabchemnitz.de/FabLab_Chemnitz/mightyscape-1.2/src/branch/master/LICENSE",
|
||||
"comment": "",
|
||||
"source_url": "https://gitea.fablabchemnitz.de/FabLab_Chemnitz/mightyscape-1.X/src/branch/master/extensions/fablabchemnitz/primitive",
|
||||
"source_url": "https://gitea.fablabchemnitz.de/FabLab_Chemnitz/mightyscape-1.2/src/branch/master/extensions/fablabchemnitz/primitive",
|
||||
"fork_url": "https://github.com/fogleman/primitive",
|
||||
"documentation_url": "https://stadtfabrikanten.org/pages/viewpage.action?pageId=78807580",
|
||||
"inkscape_gallery_url": "https://inkscape.org/~MarioVoigt/%E2%98%85primitive-for-inkscape",
|
||||
"main_authors": [
|
||||
"github.com/vmario89"
|
||||
"github.com/eridur-de"
|
||||
]
|
||||
}
|
||||
]
|
21
extensions/fablabchemnitz/printing_marks_dotted/meta.json
Normal file
21
extensions/fablabchemnitz/printing_marks_dotted/meta.json
Normal file
@ -0,0 +1,21 @@
|
||||
[
|
||||
{
|
||||
"name": "Printing Marks Dotted",
|
||||
"id": "fablabchemnitz.de.printing_marks_dotted",
|
||||
"path": "printing_marks_dotted",
|
||||
"dependent_extensions": null,
|
||||
"original_name": "Printing Marks Dotted",
|
||||
"original_id": "org.inkscape.printing.marks.dotted",
|
||||
"license": "GNU GPL v2",
|
||||
"license_url": "https://inkscape.org/~jabiertxof/%E2%98%85printing-marks-dotted",
|
||||
"comment": "ported to Inkscape v1 manually by Mario Voigt",
|
||||
"source_url": "https://gitea.fablabchemnitz.de/FabLab_Chemnitz/mightyscape-1.2/src/branch/master/extensions/fablabchemnitz/printing_marks_dotted",
|
||||
"fork_url": "https://inkscape.org/~jabiertxof/%E2%98%85printing-marks-dotted",
|
||||
"documentation_url": "https://stadtfabrikanten.org/display/IFM/Printing+Marks+Dotted",
|
||||
"inkscape_gallery_url": null,
|
||||
"main_authors": [
|
||||
"inkscape.org/jabiertxof",
|
||||
"github.com/eridur-de"
|
||||
]
|
||||
}
|
||||
]
|
@ -0,0 +1,46 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<inkscape-extension xmlns="http://www.inkscape.org/namespace/inkscape/extension">
|
||||
<name>Printing Marks Dotted</name>
|
||||
<id>fablabchemnitz.de.printing_marks_dotted</id>
|
||||
<param name="tab" type="notebook">
|
||||
<page name="marks" gui-text="Marks">
|
||||
<param name="crop_marks" type="bool" gui-text="Crop Marks">true</param>
|
||||
<param name="dotted_crop_marks" type="bool" gui-text="Dotted Crop Marks">false</param>
|
||||
<param name="bleed_marks" type="bool" gui-text="Bleed Marks">false</param>
|
||||
<param name="registration_marks" type="bool" gui-text="Registration Marks">true</param>
|
||||
<param name="star_target" type="bool" gui-text="Star Target">false</param>
|
||||
<param name="colour_bars" type="bool" gui-text="Color Bars">true</param>
|
||||
<param name="page_info" type="bool" gui-text="Page Information">false</param>
|
||||
</page>
|
||||
<page name="pos" gui-text="Positioning">
|
||||
<param name="where" type="optiongroup" appearance="combo" gui-text="Set crop marks to:">
|
||||
<option value="canvas">Canvas</option>
|
||||
<option value="selection">Selection</option>
|
||||
</param>
|
||||
<param name="unit" type="optiongroup" appearance="combo" gui-text="Unit:" >
|
||||
<option value="px">px</option>
|
||||
<option value="pt">pt</option>
|
||||
<option value="in">in</option>
|
||||
<option value="cm">cm</option>
|
||||
<option value="mm">mm</option>
|
||||
</param>
|
||||
<param name="crop_offset" type="float" min="0.0" max="9999.0" precision="3" gui-text="Offset:">5</param>
|
||||
<label appearance="header">Bleed Margin</label>
|
||||
<param name="bleed_top" type="float" indent="1" min="0.0" max="9999.0" precision="3" gui-text="Top:">5</param>
|
||||
<param name="bleed_bottom" type="float" indent="1" min="0.0" max="9999.0" precision="3" gui-text="Bottom:">5</param>
|
||||
<param name="bleed_left" type="float" indent="1" min="0.0" max="9999.0" precision="3" gui-text="Left:">5</param>
|
||||
<param name="bleed_right" type="float" indent="1" min="0.0" max="9999.0" precision="3" gui-text="Right:">5</param>
|
||||
</page>
|
||||
</param>
|
||||
<effect needs-live-preview="true">
|
||||
<object-type>all</object-type>
|
||||
<effects-menu>
|
||||
<submenu name="FabLab Chemnitz">
|
||||
<submenu name="Cutting/Plotting/Printing"/>
|
||||
</submenu>
|
||||
</effects-menu>
|
||||
</effect>
|
||||
<script>
|
||||
<command location="inx" interpreter="python">printing_marks_dotted.py</command>
|
||||
</script>
|
||||
</inkscape-extension>
|
@ -0,0 +1,475 @@
|
||||
#!/usr/bin/env python3
|
||||
'''
|
||||
This extension allows you to draw crop, registration and other
|
||||
printing marks in Inkscape.
|
||||
|
||||
Authors:
|
||||
Nicolas Dufour - Association Inkscape-fr
|
||||
Aurelio A. Heckert <aurium(a)gmail.com>
|
||||
|
||||
Copyright (C) 2008 Authors
|
||||
|
||||
This program is free software; you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as published by
|
||||
the Free Software Foundation; either version 2 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 General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with this program; if not, write to the Free Software
|
||||
Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||
'''
|
||||
|
||||
from subprocess import Popen, PIPE, STDOUT
|
||||
import math
|
||||
import inkex
|
||||
from lxml import etree
|
||||
|
||||
class PrintingMarksDotted(inkex.EffectExtension):
|
||||
|
||||
# Default parameters
|
||||
stroke_width = 0.25
|
||||
|
||||
def add_arguments(self, pars):
|
||||
pars.add_argument("--where_to_crop", default=True, help="Apply crop marks to...")
|
||||
pars.add_argument("--crop_marks", type=inkex.Boolean, default=True, help="Draw crop Marks?")
|
||||
pars.add_argument("--dotted_crop_marks", type=inkex.Boolean, default=True, help="Draw dotted crop Marks?")
|
||||
pars.add_argument("--bleed_marks", type=inkex.Boolean, default=False, help="Draw Bleed Marks?")
|
||||
pars.add_argument("--registration_marks", type=inkex.Boolean, default=False, help="Draw Registration Marks?")
|
||||
pars.add_argument("--star_target", type=inkex.Boolean, default=False, help="Draw Star Target?")
|
||||
pars.add_argument("--colour_bars", type=inkex.Boolean, default=False, help="Draw Colour Bars?")
|
||||
pars.add_argument("--page_info", type=inkex.Boolean, default=False, help="Draw Page Information?")
|
||||
pars.add_argument("--unit",default="px", help="Draw measurment")
|
||||
pars.add_argument("--crop_offset", type=float, default=0, help="Offset")
|
||||
pars.add_argument("--bleed_top", type=float, default=0, help="Bleed Top Size")
|
||||
pars.add_argument("--bleed_bottom", type=float, default=0, help="Bleed Bottom Size")
|
||||
pars.add_argument("--bleed_left", type=float, default=0, help="Bleed Left Size")
|
||||
pars.add_argument("--bleed_right",type=float, default=0, help="Bleed Right Size")
|
||||
pars.add_argument("--tab", help="The selected UI-tab when OK was pressed")
|
||||
|
||||
def addMarker(self):
|
||||
svg = self.document.getroot()
|
||||
xpathStr = '//marker[@id="scissorsCroper"]'
|
||||
maskElement = svg.xpath(xpathStr, namespaces=inkex.NSS)
|
||||
if maskElement == []:
|
||||
xpathStr = '//svg:defs'
|
||||
defs = svg.xpath(xpathStr, namespaces=inkex.NSS)
|
||||
line_attribs = {'markerWidth': "8.2212915",
|
||||
'markerHeight': "4.8983894",
|
||||
'orient': "auto",
|
||||
'id':"scissorsCroper"}
|
||||
markerElement = etree.SubElement(defs[0],inkex.addNS('marker','svg'), line_attribs)
|
||||
line_attribs = {'style': "fill:#000000;stroke:#ffffff;stroke-width:0.2;stroke-miterlimit:4;stroke-opacity:1",
|
||||
'id': "scissorsCroperPath",
|
||||
'd': "m -3.09375,-2.59375 c -0.2875213,-0.019086 -0.5530997,0.080418 -0.78125,0.25 -0.2281503,0.1695818 -0.4212781,0.4427198 -0.4375,0.75 -0.014236,0.2696628 0.032949,0.4281517 0.09375,0.53125 0.011692,0.019827 0.022314,0.017924 0.03125,0.03125 -0.074992,0.019409 -0.1886388,0.0360237 -0.34375,0.0625 -0.3217609,0.0549221 -0.7596575,0.13825127 -1.21875,0.375 l -3.03125,-1.125 c -0.2710413,-0.1042898 -0.5662791,-0.1829987 -0.875,-0.15625 -0.3087209,0.026749 -0.621076,0.1687088 -0.84375,0.4375 a 0.20792008,0.20792008 0 0 0 -0.03125,0.03125 0.20792008,0.20792008 0 0 0 -0.03125,0.0625 0.20792008,0.20792008 0 0 0 0,0.0625 0.20792008,0.20792008 0 0 0 0.03125,0.0625 0.20792008,0.20792008 0 0 0 0.03125,0.03125 0.20792008,0.20792008 0 0 0 0.09375,0.0625 l 2.9375,1.15625 -2.96875,1.125 a 0.20792008,0.20792008 0 0 0 -0.09375,0.0625 0.20792008,0.20792008 0 0 0 -0.03125,0.03125 0.20792008,0.20792008 0 0 0 -0.03125,0.0625 0.20792008,0.20792008 0 0 0 0,0.0625 0.20792008,0.20792008 0 0 0 0.03125,0.0625 0.20792008,0.20792008 0 0 0 0.03125,0.03125 C -10.094168,1.9539272 -9.4699318,1.9749423 -9,1.84375 L -5.71875,0.6875 c 0.481754,0.20541523 0.912658,0.3186677 1.1875,0.375 0.1483249,0.030401 0.2392409,0.045912 0.3125,0.0625 0.03663,0.00829 0.024599,-0.00324 0.03125,0 -0.0079,0.02335 -0.010635,0.041757 -0.03125,0.09375 -0.053917,0.1359822 -0.1506131,0.3500538 -0.09375,0.625 0.074929,0.3622982 0.3561361,0.6217769 0.65625,0.75 0.3001139,0.1282231 0.6300895,0.1440646 0.9375,0.03125 0.6444683,-0.175589 0.9014775,-0.9349259 0.625,-1.5 C -2.2324842,0.83910622 -2.4880622,0.66240891 -2.75,0.5625 -3.0119378,0.46259109 -3.2717529,0.42256233 -3.53125,0.4375 c -0.2805605,0.0161501 -0.5796777,0.0351178 -0.8125,-0.03125 -0.1944918,-0.0554414 -0.3308104,-0.18103045 -0.46875,-0.375 0.1925418,-0.25215792 0.4169804,-0.350782 0.71875,-0.375 0.3394341,-0.0272407 0.7247815,0.0434012 1.0625,0 0.010025,-6.5986e-4 0.021283,9.2632e-4 0.03125,0 0.5937358,-0.0551819 1.1050788,-0.57908524 1.0625,-1.1875 -0.00523,-0.6217326 -0.5853909,-1.0659264 -1.15625,-1.0625 z M -2.9375,-1.875 c 0.1401777,0.04894 0.2268596,0.139783 0.25,0.25 a 0.20792008,0.20792008 0 0 0 0.03125,0.03125 c 0.046997,0.1597651 -0.018243,0.2935457 -0.15625,0.40625 -0.1380068,0.1127043 -0.3531142,0.176154 -0.5,0.125 -0.1652738,-0.046651 -0.2408416,-0.1796945 -0.25,-0.34375 -0.00916,-0.1640555 0.046643,-0.3414062 0.21875,-0.4375 0.104863,-0.058549 0.2664752,-0.08005 0.40625,-0.03125 z m -0.21875,3.03125 c 0.2392165,0.047351 0.4697735,0.2941069 0.4375,0.53125 -0.010405,0.1211995 -0.066062,0.2235316 -0.1875,0.28125 C -3.0276883,2.0264684 -3.2009829,2.0387215 -3.3125,2 A 0.20792008,0.20792008 0 0 0 -3.34375,2 C -3.6474031,1.9320987 -3.710744,1.2999504 -3.40625,1.1875 a 0.20792008,0.20792008 0 0 0 0.03125,0 c 0.072689,-0.036572 0.1390112,-0.047034 0.21875,-0.03125 z"}
|
||||
pathElement = etree.SubElement(markerElement, inkex.addNS('path','svg'), line_attribs)
|
||||
|
||||
def draw_crop_line(self, x1, y1, x2, y2, name, parent):
|
||||
if self.options.dotted_crop_marks == True:
|
||||
self.addMarker()
|
||||
style = { 'stroke': '#FFFFFF', 'stroke-width': str(self.stroke_width),
|
||||
'fill': 'none'}
|
||||
else:
|
||||
style = { 'stroke': '#000000', 'stroke-width': str(self.stroke_width),
|
||||
'fill': 'none'}
|
||||
line_attribs = {'style': str(inkex.Style(style)),
|
||||
'id': name,
|
||||
'd': 'M '+str(x1)+','+str(y1)+' L '+str(x2)+','+str(y2)}
|
||||
etree.SubElement(parent, 'path', line_attribs)
|
||||
if self.options.dotted_crop_marks == True:
|
||||
style = { 'stroke': '#000000', 'stroke-width': str(self.stroke_width),
|
||||
'fill': 'none' , 'marker-end':'url(#scissorsCroper)',
|
||||
'stroke-dasharray' :'0.5,0.25', 'stroke-miterlimit':"4"}
|
||||
|
||||
line_attribs = {'style': str(inkex.Style(style)),
|
||||
'id': name + "_dotted",
|
||||
'd': 'M '+str(x1)+','+str(y1)+' L '+str(x2)+','+str(y2)}
|
||||
etree.SubElement(parent, 'path', line_attribs)
|
||||
|
||||
def draw_bleed_line(self, x1, y1, x2, y2, name, parent):
|
||||
style = { 'stroke': '#000000', 'stroke-width': str(self.stroke_width),
|
||||
'fill': 'none',
|
||||
'stroke-miterlimit': '4', 'stroke-dasharray': '4, 2, 1, 2',
|
||||
'stroke-dashoffset': '0' }
|
||||
line_attribs = {'style': str(inkex.Style(style)),
|
||||
'id': name,
|
||||
'd': 'M '+str(x1)+','+str(y1)+' L '+str(x2)+','+str(y2)}
|
||||
etree.SubElement(parent, 'path', line_attribs)
|
||||
|
||||
def draw_reg_circles(self, cx, cy, r, name, colours, parent):
|
||||
for i in range(len(colours)):
|
||||
style = {'stroke':colours[i], 'stroke-width':str(r / len(colours)),
|
||||
'fill':'none'}
|
||||
circle_attribs = {'style':str(inkex.Style(style)),
|
||||
inkex.addNS('label','inkscape'):name,
|
||||
'cx':str(cx), 'cy':str(cy),
|
||||
'r':str((r / len(colours)) * (i + 0.5))}
|
||||
etree.SubElement(parent, inkex.addNS('circle','svg'),
|
||||
circle_attribs)
|
||||
|
||||
def draw_registration_marks(self, cx, cy, rotate, name, parent):
|
||||
colours = ['#000000','#00ffff','#ff00ff','#ffff00','#000000']
|
||||
g = etree.SubElement(parent, 'g', { 'id': name })
|
||||
for i in range(len(colours)):
|
||||
style = {'fill':colours[i], 'fill-opacity':'1', 'stroke':'none'}
|
||||
r = (self.mark_size/2)
|
||||
step = r
|
||||
stroke = r / len(colours)
|
||||
regoffset = stroke * i
|
||||
regmark_attribs = {'style': str(inkex.Style(style)),
|
||||
'd': 'm' +\
|
||||
' '+str(-regoffset)+','+str(r) +\
|
||||
' '+str(-stroke) +',0' +\
|
||||
' '+str(step) +','+str(-r) +\
|
||||
' '+str(-step) +','+str(-r) +\
|
||||
' '+str(stroke) +',0' +\
|
||||
' '+str(step) +','+str(r) +\
|
||||
' '+str(-step) +','+str(r) +\
|
||||
' z',
|
||||
'transform': 'translate('+str(cx)+','+str(cy)+ \
|
||||
') rotate('+str(rotate)+')'}
|
||||
etree.SubElement(g, 'path', regmark_attribs)
|
||||
|
||||
def draw_star_target(self, cx, cy, name, parent):
|
||||
r = (self.mark_size/2)
|
||||
style = {'fill':'#000 device-cmyk(1,1,1,1)', 'fill-opacity':'1', 'stroke':'none'}
|
||||
d = ' M 0,0'
|
||||
i = 0
|
||||
while i < ( 2 * math.pi ):
|
||||
i += math.pi / 16
|
||||
d += ' L 0,0 ' +\
|
||||
' L '+ str(math.sin(i)*r) +','+ str(math.cos(i)*r) +\
|
||||
' L '+ str(math.sin(i+0.09)*r) +','+ str(math.cos(i+0.09)*r)
|
||||
regmark_attribs = {'style':str(inkex.Style(style)),
|
||||
inkex.addNS('label','inkscape'):name,
|
||||
'transform':'translate('+str(cx)+','+str(cy)+')',
|
||||
'd':d}
|
||||
etree.SubElement(parent, inkex.addNS('path','svg'),
|
||||
regmark_attribs)
|
||||
|
||||
def draw_coluor_bars(self, cx, cy, rotate, name, parent):
|
||||
g = etree.SubElement(parent, 'g', {
|
||||
'id':name,
|
||||
'transform':'translate('+str(cx)+','+str(cy)+\
|
||||
') rotate('+str(rotate)+')' })
|
||||
l = min( self.mark_size / 3, max(self.area_w,self.area_h) / 45 )
|
||||
for bar in [{'c':'*', 'stroke':'#000', 'x':0, 'y':-(l+1)},
|
||||
{'c':'r', 'stroke':'#0FF', 'x':0, 'y':0},
|
||||
{'c':'g', 'stroke':'#F0F', 'x':(l*11)+1, 'y':-(l+1)},
|
||||
{'c':'b', 'stroke':'#FF0', 'x':(l*11)+1, 'y':0}
|
||||
]:
|
||||
i = 0
|
||||
while i <= 1:
|
||||
cr = '255'
|
||||
cg = '255'
|
||||
cb = '255'
|
||||
if bar['c'] == 'r' or bar['c'] == '*' : cr = str(255*i)
|
||||
if bar['c'] == 'g' or bar['c'] == '*' : cg = str(255*i)
|
||||
if bar['c'] == 'b' or bar['c'] == '*' : cb = str(255*i)
|
||||
r_att = {'fill':'rgb('+cr+','+cg+','+cb+')',
|
||||
'stroke':bar['stroke'],
|
||||
'stroke-width':'0.5',
|
||||
'x':str((l*i*10)+bar['x']), 'y':str(bar['y']),
|
||||
'width':str(l), 'height':str(l)}
|
||||
r = etree.SubElement(g, 'rect', r_att)
|
||||
i += 0.1
|
||||
|
||||
def get_selection_area(self):
|
||||
scale = self.svg.unittouu('1px') # convert to document units
|
||||
sel_area = {}
|
||||
min_x, min_y, max_x, max_y = False, False, False, False
|
||||
for id in self.options.ids:
|
||||
sel_area[id] = {}
|
||||
for att in [ "x", "y", "width", "height" ]:
|
||||
args = [ "inkscape", "-I", id, "--query-"+att, self.options.input_file ]
|
||||
sel_area[id][att] = scale* \
|
||||
float(Popen(args, stdout=PIPE, stderr=PIPE).communicate()[0])
|
||||
current_min_x = sel_area[id]["x"]
|
||||
current_min_y = sel_area[id]["y"]
|
||||
current_max_x = sel_area[id]["x"] + \
|
||||
sel_area[id]["width"]
|
||||
current_max_y = sel_area[id]["y"] + \
|
||||
sel_area[id]["height"]
|
||||
if not min_x: min_x = current_min_x
|
||||
if not min_y: min_y = current_min_y
|
||||
if not max_x: max_x = current_max_x
|
||||
if not max_y: max_y = current_max_y
|
||||
if current_min_x < min_x: min_x = current_min_x
|
||||
if current_min_y < min_y: min_y = current_min_y
|
||||
if current_max_x > max_x: max_x = current_max_x
|
||||
if current_max_y > max_y: max_y = current_max_y
|
||||
#inkex.errormsg( '>> '+ id +
|
||||
# ' min_x:'+ str(min_x) +
|
||||
# ' min_y:'+ str(min_y) +
|
||||
# ' max_x:'+ str(max_x) +
|
||||
# ' max_y:'+ str(max_y) )
|
||||
self.area_x1 = min_x
|
||||
self.area_y1 = min_y
|
||||
self.area_x2 = max_x
|
||||
self.area_y2 = max_y
|
||||
self.area_w = max_x - min_x
|
||||
self.area_h = max_y - min_y
|
||||
|
||||
def effect(self):
|
||||
self.mark_size = self.svg.unittouu('1cm')
|
||||
self.min_mark_margin = self.svg.unittouu('3mm')
|
||||
|
||||
if self.options.where_to_crop == 'selection' :
|
||||
self.get_selection_area()
|
||||
#inkex.errormsg('Sory, the crop to selection is a TODO feature')
|
||||
#exit(1)
|
||||
else :
|
||||
svg = self.document.getroot()
|
||||
self.area_w = self.svg.unittouu(svg.get('width'))
|
||||
self.area_h = self.svg.unittouu(svg.attrib['height'])
|
||||
self.area_x1 = 0
|
||||
self.area_y1 = 0
|
||||
self.area_x2 = self.area_w
|
||||
self.area_y2 = self.area_h
|
||||
|
||||
# Get SVG document dimensions
|
||||
# self.width must be replaced by self.area_x2. same to others.
|
||||
svg = self.document.getroot()
|
||||
#self.width = width = self.svg.unittouu(svg.get('width'))
|
||||
#self.height = height = self.svg.unittouu(svg.attrib['height'])
|
||||
|
||||
# Convert parameters to user unit
|
||||
offset = self.svg.unittouu(str(self.options.crop_offset) + \
|
||||
self.options.unit)
|
||||
bt = self.svg.unittouu(str(self.options.bleed_top) + self.options.unit)
|
||||
bb = self.svg.unittouu(str(self.options.bleed_bottom) + self.options.unit)
|
||||
bl = self.svg.unittouu(str(self.options.bleed_left) + self.options.unit)
|
||||
br = self.svg.unittouu(str(self.options.bleed_right) + self.options.unit)
|
||||
# Bleed margin
|
||||
if bt < offset : bmt = 0
|
||||
else : bmt = bt - offset
|
||||
if bb < offset : bmb = 0
|
||||
else : bmb = bb - offset
|
||||
if bl < offset : bml = 0
|
||||
else : bml = bl - offset
|
||||
if br < offset : bmr = 0
|
||||
else : bmr = br - offset
|
||||
|
||||
# Define the new document limits
|
||||
offset_left = self.area_x1 - offset
|
||||
offset_right = self.area_x2 + offset
|
||||
offset_top = self.area_y1 - offset
|
||||
offset_bottom = self.area_y2 + offset
|
||||
|
||||
# Get middle positions
|
||||
middle_vertical = self.area_y1 + ( self.area_h / 2 )
|
||||
middle_horizontal = self.area_x1 + ( self.area_w / 2 )
|
||||
|
||||
# Test if printing-marks layer existis
|
||||
layer = self.document.xpath(
|
||||
'//*[@id="printing-marks" and @inkscape:groupmode="layer"]',
|
||||
namespaces=inkex.NSS)
|
||||
if layer: svg.remove(layer[0]) # remove if it existis
|
||||
# Create a new layer
|
||||
layer = etree.SubElement(svg, 'g')
|
||||
layer.set('id', 'printing-marks')
|
||||
layer.set(inkex.addNS('label', 'inkscape'), 'Printing Marks')
|
||||
layer.set(inkex.addNS('groupmode', 'inkscape'), 'layer')
|
||||
layer.set(inkex.addNS('insensitive', 'sodipodi'), 'true')
|
||||
|
||||
# Crop Mark
|
||||
if self.options.crop_marks == True:
|
||||
# Create a group for Crop Mark
|
||||
g_attribs = {inkex.addNS('label','inkscape'):'CropMarks',
|
||||
'id':'CropMarks'}
|
||||
g_crops = etree.SubElement(layer, 'g', g_attribs)
|
||||
|
||||
# Top left Mark
|
||||
self.draw_crop_line(self.area_x1, offset_top,
|
||||
self.area_x1, offset_top - self.mark_size,
|
||||
'cropTL1', g_crops)
|
||||
self.draw_crop_line(offset_left, self.area_y1,
|
||||
offset_left - self.mark_size, self.area_y1,
|
||||
'cropTL2', g_crops)
|
||||
|
||||
# Top right Mark
|
||||
self.draw_crop_line(self.area_x2, offset_top,
|
||||
self.area_x2, offset_top - self.mark_size,
|
||||
'cropTR1', g_crops)
|
||||
self.draw_crop_line(offset_right, self.area_y1,
|
||||
offset_right + self.mark_size, self.area_y1,
|
||||
'cropTR2', g_crops)
|
||||
|
||||
# Bottom left Mark
|
||||
self.draw_crop_line(self.area_x1, offset_bottom,
|
||||
self.area_x1, offset_bottom + self.mark_size,
|
||||
'cropBL1', g_crops)
|
||||
self.draw_crop_line(offset_left, self.area_y2,
|
||||
offset_left - self.mark_size, self.area_y2,
|
||||
'cropBL2', g_crops)
|
||||
|
||||
# Bottom right Mark
|
||||
self.draw_crop_line(self.area_x2, offset_bottom,
|
||||
self.area_x2, offset_bottom + self.mark_size,
|
||||
'cropBR1', g_crops)
|
||||
self.draw_crop_line(offset_right, self.area_y2,
|
||||
offset_right + self.mark_size, self.area_y2,
|
||||
'cropBR2', g_crops)
|
||||
|
||||
# Bleed Mark
|
||||
if self.options.bleed_marks == True:
|
||||
# Create a group for Bleed Mark
|
||||
g_attribs = {inkex.addNS('label','inkscape'):'BleedMarks',
|
||||
'id':'BleedMarks'}
|
||||
g_bleed = etree.SubElement(layer, 'g', g_attribs)
|
||||
|
||||
# Top left Mark
|
||||
self.draw_bleed_line(self.area_x1 - bl, offset_top - bmt,
|
||||
self.area_x1 - bl, offset_top - bmt - self.mark_size,
|
||||
'bleedTL1', g_bleed)
|
||||
self.draw_bleed_line(offset_left - bml, self.area_y1 - bt,
|
||||
offset_left - bml - self.mark_size, self.area_y1 - bt,
|
||||
'bleedTL2', g_bleed)
|
||||
|
||||
# Top right Mark
|
||||
self.draw_bleed_line(self.area_x2 + br, offset_top - bmt,
|
||||
self.area_x2 + br, offset_top - bmt - self.mark_size,
|
||||
'bleedTR1', g_bleed)
|
||||
self.draw_bleed_line(offset_right + bmr, self.area_y1 - bt,
|
||||
offset_right + bmr + self.mark_size, self.area_y1 - bt,
|
||||
'bleedTR2', g_bleed)
|
||||
|
||||
# Bottom left Mark
|
||||
self.draw_bleed_line(self.area_x1 - bl, offset_bottom + bmb,
|
||||
self.area_x1 - bl, offset_bottom + bmb + self.mark_size,
|
||||
'bleedBL1', g_bleed)
|
||||
self.draw_bleed_line(offset_left - bml, self.area_y2 + bb,
|
||||
offset_left - bml - self.mark_size, self.area_y2 + bb,
|
||||
'bleedBL2', g_bleed)
|
||||
|
||||
# Bottom right Mark
|
||||
self.draw_bleed_line(self.area_x2 + br, offset_bottom + bmb,
|
||||
self.area_x2 + br, offset_bottom + bmb + self.mark_size,
|
||||
'bleedBR1', g_bleed)
|
||||
self.draw_bleed_line(offset_right + bmr, self.area_y2 + bb,
|
||||
offset_right + bmr + self.mark_size, self.area_y2 + bb,
|
||||
'bleedBR2', g_bleed)
|
||||
|
||||
# Registration Mark
|
||||
if self.options.registration_marks == True:
|
||||
# Create a group for Registration Mark
|
||||
g_attribs = {inkex.addNS('label','inkscape'):'RegistrationMarks',
|
||||
'id':'RegistrationMarks'}
|
||||
g_center = etree.SubElement(layer, 'g', g_attribs)
|
||||
|
||||
# Left Mark
|
||||
cx = max( bml + offset, self.min_mark_margin )
|
||||
self.draw_registration_marks(self.area_x1 - cx - (self.mark_size/2),
|
||||
middle_vertical - self.mark_size*1.5,
|
||||
'0', 'regMarkL', g_center)
|
||||
|
||||
# Right Mark
|
||||
cx = max( bmr + offset, self.min_mark_margin )
|
||||
self.draw_registration_marks(self.area_x2 + cx + (self.mark_size/2),
|
||||
middle_vertical - self.mark_size*1.5,
|
||||
'180', 'regMarkR', g_center)
|
||||
|
||||
# Top Mark
|
||||
cy = max( bmt + offset, self.min_mark_margin )
|
||||
self.draw_registration_marks(middle_horizontal,
|
||||
self.area_y1 - cy - (self.mark_size/2),
|
||||
'90', 'regMarkT', g_center)
|
||||
|
||||
# Bottom Mark
|
||||
cy = max( bmb + offset, self.min_mark_margin )
|
||||
self.draw_registration_marks(middle_horizontal,
|
||||
self.area_y2 + cy + (self.mark_size/2),
|
||||
'-90', 'regMarkB', g_center)
|
||||
|
||||
# Star Target
|
||||
if self.options.star_target == True:
|
||||
# Create a group for Star Target
|
||||
g_attribs = {inkex.addNS('label','inkscape'):'StarTarget',
|
||||
'id':'StarTarget'}
|
||||
g_center = etree.SubElement(layer, 'g', g_attribs)
|
||||
|
||||
if self.area_h < self.area_w :
|
||||
# Left Star
|
||||
cx = max( bml + offset, self.min_mark_margin )
|
||||
self.draw_star_target(self.area_x1 - cx - (self.mark_size/2),
|
||||
middle_vertical,
|
||||
'starTargetL', g_center)
|
||||
# Right Star
|
||||
cx = max( bmr + offset, self.min_mark_margin )
|
||||
self.draw_star_target(self.area_x2 + cx + (self.mark_size/2),
|
||||
middle_vertical,
|
||||
'starTargetR', g_center)
|
||||
else :
|
||||
# Top Star
|
||||
cy = max( bmt + offset, self.min_mark_margin )
|
||||
self.draw_star_target(middle_horizontal - self.mark_size*1.5,
|
||||
self.area_y1 - cy - (self.mark_size/2),
|
||||
'starTargetT', g_center)
|
||||
# Bottom Star
|
||||
cy = max( bmb + offset, self.min_mark_margin )
|
||||
self.draw_star_target(middle_horizontal - self.mark_size*1.5,
|
||||
self.area_y2 + cy + (self.mark_size/2),
|
||||
'starTargetB', g_center)
|
||||
|
||||
|
||||
# Colour Bars
|
||||
if self.options.colour_bars == True:
|
||||
# Create a group for Colour Bars
|
||||
g_attribs = {inkex.addNS('label','inkscape'):'ColourBars',
|
||||
'id':'PrintingColourBars'}
|
||||
g_center = etree.SubElement(layer, 'g', g_attribs)
|
||||
|
||||
if self.area_h > self.area_w :
|
||||
# Left Bars
|
||||
cx = max( bml + offset, self.min_mark_margin )
|
||||
self.draw_coluor_bars(self.area_x1 - cx - (self.mark_size/2),
|
||||
middle_vertical + self.mark_size,
|
||||
90,
|
||||
'PrintingColourBarsL', g_center)
|
||||
# Right Bars
|
||||
cx = max( bmr + offset, self.min_mark_margin )
|
||||
self.draw_coluor_bars(self.area_x2 + cx + (self.mark_size/2),
|
||||
middle_vertical + self.mark_size,
|
||||
90,
|
||||
'PrintingColourBarsR', g_center)
|
||||
else :
|
||||
# Top Bars
|
||||
cy = max( bmt + offset, self.min_mark_margin )
|
||||
self.draw_coluor_bars(middle_horizontal + self.mark_size,
|
||||
self.area_y1 - cy - (self.mark_size/2),
|
||||
0,
|
||||
'PrintingColourBarsT', g_center)
|
||||
# Bottom Bars
|
||||
cy = max( bmb + offset, self.min_mark_margin )
|
||||
self.draw_coluor_bars(middle_horizontal + self.mark_size,
|
||||
self.area_y2 + cy + (self.mark_size/2),
|
||||
0,
|
||||
'PrintingColourBarsB', g_center)
|
||||
|
||||
|
||||
# Page Information
|
||||
if self.options.page_info == True:
|
||||
# Create a group for Page Information
|
||||
g_attribs = {inkex.addNS('label','inkscape'):'PageInformation',
|
||||
'id':'PageInformation'}
|
||||
g_pag_info = etree.SubElement(layer, 'g', g_attribs)
|
||||
y_margin = max( bmb + offset, self.min_mark_margin )
|
||||
txt_attribs = {
|
||||
'style': 'font-size:12px;font-style:normal;font-weight:normal;fill:#000000;font-family:Bitstream Vera Sans,sans-serif;text-anchor:middle;text-align:center',
|
||||
'x': str(middle_horizontal),
|
||||
'y': str(self.area_y2+y_margin+self.mark_size+20)
|
||||
}
|
||||
txt = etree.SubElement(g_pag_info, 'text', txt_attribs)
|
||||
txt.text = 'Page size: ' +\
|
||||
str(round(self.svg.uutounit(self.area_w,self.options.unit),2)) +\
|
||||
'x' +\
|
||||
str(round(self.svg.uutounit(self.area_h,self.options.unit),2)) +\
|
||||
' ' + self.options.unit
|
||||
|
||||
|
||||
if __name__ == '__main__':
|
||||
PrintingMarksDotted().run()
|
@ -0,0 +1,21 @@
|
||||
[
|
||||
{
|
||||
"name": "Silhouette Cameo Registration Marks",
|
||||
"id": "fablabchemnitz.de.render_silhouette_regmarks",
|
||||
"path": "render_silhouette_regmarks",
|
||||
"dependent_extensions": null,
|
||||
"original_name": "Classic",
|
||||
"original_id": "org.inkscape.render.silhouette-regmarks",
|
||||
"license": "GNU GPL v3",
|
||||
"license_url": "https://github.com/miLORD1337/silhouette-regmarks/blob/main/LICENSE",
|
||||
"comment": "",
|
||||
"source_url": "https://gitea.fablabchemnitz.de/FabLab_Chemnitz/mightyscape-1.2/src/branch/master/extensions/fablabchemnitz/render_silhouette_regmarks",
|
||||
"fork_url": "https://github.com/miLORD1337/silhouette-regmarks",
|
||||
"documentation_url": "https://stadtfabrikanten.org/display/IFM/Silhouette+Cameo+Registration+Marks",
|
||||
"inkscape_gallery_url": null,
|
||||
"main_authors": [
|
||||
"github.com/miLORD1337",
|
||||
"github.com/eridur-de"
|
||||
]
|
||||
}
|
||||
]
|
@ -0,0 +1,21 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<inkscape-extension xmlns="http://www.inkscape.org/namespace/inkscape/extension">
|
||||
<name>Silhouette Cameo Registration Marks</name>
|
||||
<id>fablabchemnitz.de.silhouette_cameo_registration_marks</id>
|
||||
<param name="regwidth" type="float" min="0.0" max="10000" gui-text="X mark distance [mm]">180</param>
|
||||
<param name="reglength" type="float" min="0.0" max="10000" gui-text="Y mark distance [mm]">230</param>
|
||||
<param name="regoriginx" type="float" min="10.0" max="10000" gui-text="Position of regmark from document left [mm]">15</param>
|
||||
<param name="regoriginy" type="float" min="10.0" max="10000" gui-text="Position of regmark from document top [mm]">20</param>
|
||||
<label>Distance of the registration mark edges</label>
|
||||
<effect>
|
||||
<object-type>all</object-type>
|
||||
<effects-menu>
|
||||
<submenu name="FabLab Chemnitz">
|
||||
<submenu name="Cutting/Plotting/Printing"/>
|
||||
</submenu>
|
||||
</effects-menu>
|
||||
</effect>
|
||||
<script>
|
||||
<command location="inx" interpreter="python">render_silhouette_regmarks.py</command>
|
||||
</script>
|
||||
</inkscape-extension>
|
@ -0,0 +1,101 @@
|
||||
#
|
||||
# Copyright (C) 2021 miLORD1337
|
||||
#
|
||||
# This program is free software; you can redistribute it and/or modify
|
||||
# it under the terms of the GNU General Public License as published by
|
||||
# the Free Software Foundation; either version 2 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 General Public License for more details.
|
||||
#
|
||||
# You should have received a copy of the GNU General Public License
|
||||
# along with this program; if not, write to the Free Software
|
||||
# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110, USA.
|
||||
#
|
||||
"""
|
||||
Base module for rendering regmarks for Silhouette CAMEO products in Inkscape.
|
||||
"""
|
||||
|
||||
import inkex
|
||||
from lxml import etree
|
||||
|
||||
SVG_URI = u'http://www.w3.org/2000/svg'
|
||||
|
||||
class SilhouetteCameoRegistrationMarks(inkex.EffectExtension):
|
||||
|
||||
def add_arguments(self, pars):
|
||||
# Define string option "--what" with "-w" shortcut and default value "World".
|
||||
# Layer name static, since self.document.getroot() not available on initialization
|
||||
self.layername = 'silhouette-regmark'
|
||||
|
||||
# Parse arguments
|
||||
pars.add_argument("-X", "--reg-x", "--regwidth", type = float, dest = "regwidth", default = 180.0, help="X mark distance [mm]")
|
||||
pars.add_argument("-Y", "--reg-y", "--reglength", type = float, dest = "reglength", default = 230.0, help="Y mark distance [mm]")
|
||||
pars.add_argument("--rego-x", "--regoriginx", type = float, dest = "regoriginx", default = 15.0, help="X mark origin from left [mm]")
|
||||
pars.add_argument("--rego-y", "--regoriginy", type = float, dest = "regoriginy", default = 20.0, help="X mark origin from top [mm]")
|
||||
|
||||
#SVG rect element generation routine
|
||||
def drawRect(self, size, pos, name):
|
||||
x, y = pos
|
||||
w, h = size
|
||||
rect = etree.Element('{%s}rect' % SVG_URI)
|
||||
rect.set('x', str(x))
|
||||
rect.set('y', str(y))
|
||||
rect.set('id', name)
|
||||
rect.set('width', str(w))
|
||||
rect.set('height', str(h))
|
||||
rect.set('style', 'fill: black;')
|
||||
return rect
|
||||
|
||||
#SVG line element generation routine
|
||||
def drawLine(self, posStart, posEnd, name):
|
||||
x1, y1 = posStart
|
||||
x2, y2, = posEnd
|
||||
line = etree.Element('{%s}line' % SVG_URI)
|
||||
line.set('x1', str(x1))
|
||||
line.set('y1', str(y1))
|
||||
line.set('x2', str(x2))
|
||||
line.set('y2', str(y2))
|
||||
line.set('id', name)
|
||||
line.set('style', 'stroke: black; stroke-width: 0.5;')
|
||||
return line
|
||||
|
||||
def effect(self):
|
||||
svg = self.document.getroot()
|
||||
|
||||
# Create a new layer.
|
||||
layer = etree.SubElement(svg, 'g')
|
||||
layer.set(inkex.addNS('label', 'inkscape'), self.layername)
|
||||
layer.set(inkex.addNS('groupmode', 'inkscape'), 'layer')
|
||||
|
||||
# Create square in top left corner
|
||||
layer.append(self.drawRect((5,5), (self.options.regoriginx,self.options.regoriginy), 'TopLeft'))
|
||||
|
||||
# Create group for top right corner
|
||||
topRight = etree.Element('{%s}g' % SVG_URI)
|
||||
topRight.set('id', 'TopRight')
|
||||
topRight.set('style', 'fill: black;')
|
||||
|
||||
# Create horizontal and vertical lines in group
|
||||
topRight.append(self.drawLine((self.options.regwidth-20,self.options.regoriginy), (self.options.regwidth,self.options.regoriginy), 'Horizontal'))
|
||||
topRight.append(self.drawLine((self.options.regwidth,self.options.regoriginy), (self.options.regwidth,self.options.regoriginy + 20), 'Vertical'))
|
||||
layer.append(topRight)
|
||||
|
||||
# Create group for top right corner
|
||||
bottomLeft = etree.Element('{%s}g' % SVG_URI)
|
||||
bottomLeft.set('id', 'BottomLeft')
|
||||
bottomLeft.set('style', 'fill: black;')
|
||||
|
||||
# Create horizontal and vertical lines in group
|
||||
bottomLeft.append(self.drawLine((self.options.regoriginx,self.options.reglength), (self.options.regoriginx+20,self.options.reglength), 'Horizontal'))
|
||||
bottomLeft.append(self.drawLine((self.options.regoriginx,self.options.reglength), (self.options.regoriginx,self.options.reglength - 20), 'Vertical'))
|
||||
layer.append(bottomLeft)
|
||||
|
||||
#Lock layer
|
||||
layer.set(inkex.addNS('insensitive', 'sodipodi'), 'true')
|
||||
|
||||
if __name__ == '__main__':
|
||||
SilhouetteCameoRegistrationMarks().run()
|
@ -7,14 +7,14 @@
|
||||
"original_name": "Scale To Size",
|
||||
"original_id": "fablabchemnitz.de.scale_to_size",
|
||||
"license": "GNU GPL v3",
|
||||
"license_url": "https://gitea.fablabchemnitz.de/FabLab_Chemnitz/mightyscape-1.X/src/branch/master/LICENSE",
|
||||
"license_url": "https://gitea.fablabchemnitz.de/FabLab_Chemnitz/mightyscape-1.2/src/branch/master/LICENSE",
|
||||
"comment": "",
|
||||
"source_url": "https://gitea.fablabchemnitz.de/FabLab_Chemnitz/mightyscape-1.X/src/branch/master/extensions/fablabchemnitz/scale_to_size",
|
||||
"source_url": "https://gitea.fablabchemnitz.de/FabLab_Chemnitz/mightyscape-1.2/src/branch/master/extensions/fablabchemnitz/scale_to_size",
|
||||
"fork_url": null,
|
||||
"documentation_url": "https://stadtfabrikanten.org/pages/viewpage.action?pageId=76054572",
|
||||
"inkscape_gallery_url": null,
|
||||
"main_authors": [
|
||||
"github.com/vmario89"
|
||||
"github.com/eridur-de"
|
||||
]
|
||||
}
|
||||
]
|
@ -9,13 +9,13 @@
|
||||
"license": "GNU GPL v3",
|
||||
"license_url": "https://inkscape.org/de/~pakin/%E2%98%85snap-object-points",
|
||||
"comment": "",
|
||||
"source_url": "https://gitea.fablabchemnitz.de/FabLab_Chemnitz/mightyscape-1.X/src/branch/master/extensions/fablabchemnitz/snap_object_points",
|
||||
"source_url": "https://gitea.fablabchemnitz.de/FabLab_Chemnitz/mightyscape-1.2/src/branch/master/extensions/fablabchemnitz/snap_object_points",
|
||||
"fork_url": "https://inkscape.org/de/~pakin/%E2%98%85snap-object-points",
|
||||
"documentation_url": "",
|
||||
"inkscape_gallery_url": null,
|
||||
"main_authors": [
|
||||
"inkscape.org/pakin",
|
||||
"github.com/vmario89"
|
||||
"github.com/eridur-de"
|
||||
]
|
||||
}
|
||||
]
|
@ -9,13 +9,13 @@
|
||||
"license": "GNU GPL v3",
|
||||
"license_url": "https://inkscape.org/de/~jabiertxof/%E2%98%85stroke-color-as-fill",
|
||||
"comment": "ported to Inkscape v1 by Mario Voigt",
|
||||
"source_url": "https://gitea.fablabchemnitz.de/FabLab_Chemnitz/mightyscape-1.X/src/branch/master/extensions/fablabchemnitz/stroke_color_as_fill",
|
||||
"source_url": "https://gitea.fablabchemnitz.de/FabLab_Chemnitz/mightyscape-1.2/src/branch/master/extensions/fablabchemnitz/stroke_color_as_fill",
|
||||
"fork_url": "https://inkscape.org/de/~jabiertxof/%E2%98%85stroke-color-as-fill",
|
||||
"documentation_url": "https://stadtfabrikanten.org/display/IFM/Stroke+Color+As+Fill",
|
||||
"inkscape_gallery_url": null,
|
||||
"main_authors": [
|
||||
"inkscape.org/jabiertxof",
|
||||
"github.com/vmario89"
|
||||
"github.com/eridur-de"
|
||||
]
|
||||
}
|
||||
]
|
266
extensions/fablabchemnitz/table_support/base_transform.py
Normal file
266
extensions/fablabchemnitz/table_support/base_transform.py
Normal file
@ -0,0 +1,266 @@
|
||||
#!/usr/bin/env python3
|
||||
"""
|
||||
base_transform.py
|
||||
Base matemathical operations for SVG 3x3 matrices
|
||||
|
||||
Copyright (C) 2011 Cosmin Popescu, cosminadrianpopescu@gmail.com
|
||||
|
||||
This program is free software; you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as published by
|
||||
the Free Software Foundation; either version 2 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 General Public License for more details.
|
||||
"""
|
||||
|
||||
import re
|
||||
import inkex
|
||||
import os
|
||||
from math import *
|
||||
|
||||
class BaseTransform(inkex.Effect):
|
||||
unitMatrix = [[1, 0, 0], [0, 1, 0], [0, 0, 1]]
|
||||
|
||||
def isset(self, v, i = None):
|
||||
try:
|
||||
if (i is None):
|
||||
v
|
||||
else:
|
||||
v[i]
|
||||
return True
|
||||
except:
|
||||
return False
|
||||
|
||||
def __init__(self):
|
||||
inkex.Effect.__init__(self)
|
||||
|
||||
def sizeToPx(self, s, dim = "y"):
|
||||
root = self.document.getroot()
|
||||
try:
|
||||
factor = float(root.attrib[inkex.addNS('export-' + dim + 'dpi', 'inkscape')])
|
||||
except:
|
||||
factor = 90
|
||||
unit = ''
|
||||
pattern = '[\\-\\d\\.]+([a-zA-Z][a-zA-Z])'
|
||||
if (re.search(pattern, s)):
|
||||
res = re.search(pattern, s)
|
||||
unit = res.group(1)
|
||||
pattern = '^([\\-\\d\\.]*)'
|
||||
res = re.search(pattern, s)
|
||||
n = float(res.group(1))
|
||||
if unit == 'cm':
|
||||
return (n / 2.54) * factor
|
||||
elif unit == 'ft':
|
||||
return n * 12 * factor
|
||||
elif unit == 'in':
|
||||
return n * factor
|
||||
elif unit == 'm':
|
||||
return ((n * 10) / 2.54) * factor
|
||||
elif unit == 'mm':
|
||||
return ((n / 10) / 2.54) * factor
|
||||
elif unit == 'pc':
|
||||
return ((n * 2.36228956229) / 2.54) * factor
|
||||
elif unit == 'pt':
|
||||
return (((n / 2.83464646465) / 10) / 2.54) * factor
|
||||
elif unit == 'px' or unit == '':
|
||||
return n
|
||||
|
||||
return 0
|
||||
|
||||
def transform(self, el):
|
||||
result = self.unitMatrix
|
||||
if (el.tag == inkex.addNS('svg', 'svg')):
|
||||
return result
|
||||
|
||||
if (not self.isset(el.attrib, 'transform')):
|
||||
return self.multiply(self.transform(el.getparent()), result)
|
||||
pattern = '(matrix|translate|scale|rotate|skewX|skewY)[\\s|,]*\\(([^\\)]*)\\)'
|
||||
transforms = re.findall(pattern, el.attrib['transform'])
|
||||
|
||||
for transform in transforms:
|
||||
values = re.split('[\\s|,]+', transform[1])
|
||||
for i in range(len(values)):
|
||||
values[i] = float(values[i])
|
||||
function = transform[0]
|
||||
if (function == 'matrix'):
|
||||
a = [[values[0], values[2], values[4]],
|
||||
[values[1], values[3], values[5]],
|
||||
[0, 0, 1]]
|
||||
result = self.multiply(result, a)
|
||||
elif (function == 'translate'):
|
||||
a = [[1, 0, values[0]],
|
||||
[0, 1, values[1]],
|
||||
[0, 0, 1]]
|
||||
result = self.multiply(result, a)
|
||||
elif (function == 'scale'):
|
||||
a = [[values[0], 0, 0],
|
||||
[0, values[1], 0],
|
||||
[0, 0, 1]]
|
||||
result = self.multiply(result, a)
|
||||
elif (function == 'rotate'):
|
||||
if (len(values) == 1):
|
||||
a = [[math.cos(values[0]), -math.sin(values[0]), 0],
|
||||
[math.sin(values[0]), math.cos(values[0]), 0],
|
||||
[0, 0, 1]]
|
||||
result = self.multiply(result, a)
|
||||
else:
|
||||
a = [[1, 0, values[2]],
|
||||
[0, 1, values[2]],
|
||||
[0, 0, 1]]
|
||||
result = self.multiply(result, a)
|
||||
a = [[math.cos(values[0]), -math.sin(values[0]), 0],
|
||||
[math.sin(values[0]), math.cos(values[0]), 0],
|
||||
[0, 0, 1]]
|
||||
result = self.multiply(result, a)
|
||||
a = [[1, 0, -values[2]],
|
||||
[0, 1, -values[2]],
|
||||
[0, 0, 1]]
|
||||
result = self.multiply(result, a)
|
||||
elif (function == 'skewX'):
|
||||
a = [[1, math.tan(values[0]), 0],
|
||||
[0, 1, 0],
|
||||
[0, 0, 1]]
|
||||
result = self.multiply(result, a)
|
||||
elif (function == 'skewY'):
|
||||
a = [[1, 0, 0],
|
||||
[math.tan(values[0]), 1, 0],
|
||||
[0, 0, 1]]
|
||||
result = self.multiply(result, a)
|
||||
|
||||
return self.multiply(self.transform(el.getparent()), result)
|
||||
|
||||
|
||||
def getPosition(self, el):
|
||||
if not self.isset(el.attrib, 'x'):
|
||||
return False
|
||||
|
||||
x = self.sizeToPx(el.attrib['x'], 'x')
|
||||
y = self.sizeToPx(el.attrib['y'], 'y')
|
||||
v = [x, y, 1]
|
||||
t = self.transform(el)
|
||||
v = self.multiply(t, v)
|
||||
|
||||
return {'coordinates': v, 'matrix': t}
|
||||
|
||||
def setPosition(self, el, position):
|
||||
c = position['coordinates']
|
||||
a = position['matrix']
|
||||
if (not self.isUnitMatrix(a)):
|
||||
c = self.multiply(self.inverse(a), c)
|
||||
el.set('x', str(c[0]))
|
||||
el.set('y', str(c[1]))
|
||||
|
||||
|
||||
def determinant(self, a):
|
||||
if len(a) != 3:
|
||||
return False
|
||||
if (len(a[0]) != 3):
|
||||
return False
|
||||
|
||||
det = a[0][0] * (a[1][1] * a[2][2] - a[2][1] * a[1][2]) - a[0][1] * (a[1][0] * a[2][2] - a[2][0] * a[1][2]) + a[0][2] * (a[1][0] * a[2][1] - a[2][0] * a[1][1])
|
||||
|
||||
if (det == 0):
|
||||
det = 0.00001
|
||||
|
||||
return det
|
||||
|
||||
def minors(self, a):
|
||||
if len(a) != 3:
|
||||
return False
|
||||
if (len(a[0]) != 3):
|
||||
return False
|
||||
|
||||
return [[a[1][1] * a[2][2] - a[2][1] * a[1][2], a[1][0] * a[2][2] - a[2][0] * a[1][2], a[1][0] * a[2][1] - a[2][0] * a[1][1]],
|
||||
[a[0][1] * a[2][2] - a[2][1] * a[0][2], a[0][0] * a[2][2] - a[0][2] * a[2][0], a[0][0] * a[2][1] - a[2][0] * a[0][1]],
|
||||
[a[0][1] * a[1][2] - a[1][1] * a[0][2], a[0][0] * a[1][2] - a[0][1] * a[0][2], a[0][0] * a[1][1] - a[1][0] * a[0][1]]
|
||||
]
|
||||
|
||||
def cofactors(self, a):
|
||||
if len(a) != 3:
|
||||
return False
|
||||
if (len(a[0]) != 3):
|
||||
return False
|
||||
|
||||
return [[a[0][0], -a[0][1], a[0][2]],
|
||||
[-a[1][0], a[1][1], -a[1][2]],
|
||||
[a[2][0], -a[2][1], a[2][2]]
|
||||
]
|
||||
|
||||
def adjoint(self, a):
|
||||
if len(a) != 3:
|
||||
return False
|
||||
if (len(a[0]) != 3):
|
||||
return False
|
||||
|
||||
return [[a[0][0], a[1][0], a[2][0]],
|
||||
[a[0][1], a[1][1], a[2][1]],
|
||||
[a[0][2], a[1][2], a[2][2]]
|
||||
]
|
||||
|
||||
def inverse(self, a):
|
||||
if len(a) != 3:
|
||||
return False
|
||||
if (len(a[0]) != 3):
|
||||
return False
|
||||
|
||||
det = self.determinant(a)
|
||||
m = self.minors(a)
|
||||
c = self.cofactors(m)
|
||||
adj = self.adjoint(c)
|
||||
|
||||
return [[adj[0][0] / det, adj[0][1] / det, adj[0][2] / det],
|
||||
[adj[1][0] / det, adj[1][1] / det, adj[1][2] / det],
|
||||
[adj[2][0] / det, adj[2][1] / det, adj[2][2] / det]
|
||||
]
|
||||
|
||||
def multiply(self, a, v):
|
||||
if len(a) != 3:
|
||||
return False
|
||||
if (len(a[0]) != 3):
|
||||
return False
|
||||
|
||||
if (len(v) != 3):
|
||||
return False
|
||||
|
||||
if (not self.isset(v[0], 0)):
|
||||
return [a[0][0] * v[0] + a[0][1] * v[1] + a[0][2] * v[2],
|
||||
a[1][0] * v[0] + a[1][1] * v[1] + a[1][2] * v[2],
|
||||
a[2][0] * v[0] + a[2][1] * v[1] + a[2][2] * v[2]
|
||||
]
|
||||
else:
|
||||
return [[a[0][0] * v[0][0] + a[0][1] * v[1][0] + a[0][2] * v[2][0], a[0][0] * v[0][1] + a[0][1] * v[1][1] + a[0][2] * v[2][1], a[0][0] * v[0][2] + a[0][1] * v[1][2] + a[0][2] * v[2][2]],
|
||||
[a[1][0] * v[0][0] + a[1][1] * v[1][0] + a[1][2] * v[2][0], a[1][0] * v[0][1] + a[1][1] * v[1][1] + a[1][2] * v[2][1], a[1][0] * v[0][2] + a[1][1] * v[1][2] + a[1][2] * v[2][2]],
|
||||
[a[2][0] * v[0][0] + a[2][1] * v[1][0] + a[2][2] * v[2][0], a[2][0] * v[0][1] + a[2][1] * v[1][1] + a[2][2] * v[2][1], a[2][0] * v[0][2] + a[2][1] * v[1][2] + a[2][2] * v[2][2]]
|
||||
]
|
||||
|
||||
def isUnitMatrix(self, a):
|
||||
if (len(a) != 3):
|
||||
return False
|
||||
if (len(a[0]) != 3):
|
||||
return False
|
||||
|
||||
for i in range(3):
|
||||
for j in range(3):
|
||||
if (a[i][j] != self.unitMatrix[i][j]):
|
||||
return False
|
||||
|
||||
return True
|
||||
|
||||
def reParse(self):
|
||||
if os.name == 'nt':
|
||||
path = os.environ['USERPROFILE']
|
||||
else:
|
||||
path = os.path.expanduser("~")
|
||||
text = inkex.etree.tostring(self.document.getroot())
|
||||
f = open(path + '/tmp.svg', 'w')
|
||||
f.write(text)
|
||||
f.close()
|
||||
self.parse(path + '/tmp.svg')
|
||||
|
||||
os.remove(path + '/tmp.svg')
|
||||
|
||||
def matrix2string(self, a):
|
||||
return 'matrix(' + str(a[0][0]) + ',' + str(a[1][0]) + ',' + str(a[0][1]) + ',' + str(a[1][1]) + ',' + str(a[0][2]) + ',' + str(a[1][2]) + ')'
|
21
extensions/fablabchemnitz/table_support/meta.json
Normal file
21
extensions/fablabchemnitz/table_support/meta.json
Normal file
@ -0,0 +1,21 @@
|
||||
[
|
||||
{
|
||||
"name": "<various>",
|
||||
"id": "fablabchemnitz.de.table_<various>",
|
||||
"path": "table_support",
|
||||
"dependent_extensions": null,
|
||||
"original_name": "<various>",
|
||||
"original_id": "org.greygreen.inkscape.effects.table_<various>",
|
||||
"license": "GNU GPL v2",
|
||||
"license_url": "https://sourceforge.net/projects/inkscape-tables/files/inkscape-table-1.0.tar.gz/download",
|
||||
"comment": "ported to Inkscape v1 by Mario Voigt",
|
||||
"source_url": "https://gitea.fablabchemnitz.de/FabLab_Chemnitz/mightyscape-1.2/src/branch/master/extensions/fablabchemnitz/table_support",
|
||||
"fork_url": "https://sourceforge.net/projects/inkscape-tables",
|
||||
"documentation_url": "https://stadtfabrikanten.org/display/IFM/Table+Support",
|
||||
"inkscape_gallery_url": null,
|
||||
"main_authors": [
|
||||
"sourceforge.net/lixapopescu",
|
||||
"github.com/eridur-de"
|
||||
]
|
||||
}
|
||||
]
|
850
extensions/fablabchemnitz/table_support/table.py
Normal file
850
extensions/fablabchemnitz/table_support/table.py
Normal file
@ -0,0 +1,850 @@
|
||||
"""
|
||||
table.py
|
||||
Table support for Inkscape
|
||||
|
||||
Copyright (C) 2011 Cosmin Popescu, cosminadrianpopescu@gmail.com
|
||||
|
||||
This program is free software; you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as published by
|
||||
the Free Software Foundation; either version 2 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 General Public License for more details.
|
||||
"""
|
||||
import math
|
||||
|
||||
import inkex
|
||||
from inkex import Guide
|
||||
from lxml import etree
|
||||
import base_transform
|
||||
import re
|
||||
|
||||
class TableEngine(base_transform.BaseTransform):
|
||||
|
||||
defaultId = 'inkscape-table'
|
||||
cell_type_row = 'row'
|
||||
cell_type_column = 'column'
|
||||
normalizeFactor = 5
|
||||
tablesCount = 0
|
||||
tables = None
|
||||
selectedTables = {}
|
||||
mergedCells = {}
|
||||
tablesTexts = {}
|
||||
get_tables = True
|
||||
auto_split = True
|
||||
delimiter = ','
|
||||
|
||||
def __init__(self, get_tables = True, auto_split = True):
|
||||
inkex.NSS['inkex'] = 'http://sodipodi.sourceforge.net/DTD/inkex-0.dtd'
|
||||
self.get_tables = get_tables
|
||||
self.auto_split = auto_split
|
||||
base_transform.BaseTransform.__init__(self)
|
||||
|
||||
def getTablesCount(self):
|
||||
node = self.document.xpath('//inkex:tables', namespaces = inkex.NSS)
|
||||
if len(node) == 0:
|
||||
xml = '<inkex:tables xmlns:inkex="http://sodipodi.sourceforge.net/DTD/inkex-0.dtd" count="0"/>'
|
||||
self.document.getroot().append(etree.fromstring(xml))
|
||||
node = self.document.xpath('//inkex:tables', namespaces = inkex.NSS)
|
||||
else:
|
||||
self.tablesCount = int(node[0].attrib['count'])
|
||||
|
||||
self.tables = node[0]
|
||||
|
||||
def isTableCell(self, id):
|
||||
el = self.svg.getElementById(id)
|
||||
if (el == None):
|
||||
return False
|
||||
|
||||
if (self.isset(el.attrib, inkex.addNS('table-id', 'inkex'))):
|
||||
tableId = el.attrib[inkex.addNS('table-id', 'inkex')]
|
||||
if (re.search('\\-text$', tableId)):
|
||||
return False
|
||||
else:
|
||||
return True
|
||||
|
||||
return False
|
||||
|
||||
def effect(self):
|
||||
self.getTablesCount()
|
||||
if (self.get_tables):
|
||||
self.getAllTables()
|
||||
if (self.auto_split):
|
||||
for id, table in self.selectedTables.items():
|
||||
for i in range(len(table)):
|
||||
for j in range(len(table[i])):
|
||||
if (table[i][j] != None):
|
||||
points = self.splitCell(table[i][j])
|
||||
if (points != False):
|
||||
if (self.isset(self.mergedCells, id)):
|
||||
self.mergedCells[id].append(points)
|
||||
else:
|
||||
self.mergedCells[id] = [points]
|
||||
for tableId in self.mergedCells:
|
||||
self.getTable(tableId)
|
||||
self.doinkex()
|
||||
if (self.get_tables):
|
||||
if (self.auto_split):
|
||||
for tableId in self.mergedCells:
|
||||
self.getTableText(tableId)
|
||||
for points in self.mergedCells[tableId]:
|
||||
if (not self.isset(points, 'removed')):
|
||||
self.mergeTable(tableId, points)
|
||||
|
||||
def newCell(self, x, y, width, height, id, i, j, transform = None):
|
||||
#path = '//*[@inkex:table-id="%s"]' % id
|
||||
_id = self.svg.get_unique_id(id)
|
||||
etree.SubElement(self.svg.get_current_layer(), 'rect', {
|
||||
'id': _id,
|
||||
'style': 'fill:none;stroke:#000000;stroke-width:1px;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none',
|
||||
'width': str(width) + 'px',
|
||||
'height': str(height) + 'px',
|
||||
'x': str(x) + 'px',
|
||||
'y': str(y) + 'px',
|
||||
inkex.addNS('table-id', 'inkex'): id,
|
||||
inkex.addNS('row', 'inkex'): str(i),
|
||||
inkex.addNS('column', 'inkex'): str(j)
|
||||
})
|
||||
|
||||
if (transform != None):
|
||||
el = self.svg.getElementById(_id)
|
||||
el.set('transform', transform)
|
||||
|
||||
return _id
|
||||
|
||||
'''
|
||||
_id = self.svg.get_unique_id(id)
|
||||
content = '<rect style="fill:none;stroke:#000000;stroke-width:1px;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none"\n\
|
||||
id="' + _id + '"\n\
|
||||
width="' + str(width) + '"\n\
|
||||
height="' + str(height) + '"\n\
|
||||
x="' + str(x) + '"\n\
|
||||
y="' + str(y) + '"\n\
|
||||
/>'
|
||||
|
||||
self.svg.get_current_layer().append(etree.XML(content))
|
||||
el = self.svg.getElementById(_id)
|
||||
el.set(inkex.addNS('table-id', 'inkex'), id)
|
||||
el.set(inkex.addNS('row', 'inkex'), str(i))
|
||||
el.set(inkex.addNS('column', 'inkex'), str(j))
|
||||
'''
|
||||
|
||||
def create(self, width, height, cols, rows):
|
||||
tableId = self.defaultId + str(self.tablesCount)
|
||||
self.tablesCount += 1
|
||||
self.tables.set('count', str(self.tablesCount))
|
||||
content = '<inkex:table xmlns:inkex="http://sodipodi.sourceforge.net/DTD/inkex-0.dtd" table-id="' + tableId + '" rows="' + str(rows) + '" columns="' + str(cols) + '"/>'
|
||||
self.tables.append(etree.fromstring(content))
|
||||
|
||||
width = self.sizeToPx(width, 'x')
|
||||
height = self.sizeToPx(height, 'y')
|
||||
|
||||
x = 0
|
||||
y = 0
|
||||
|
||||
content = ''
|
||||
|
||||
for i in range(rows):
|
||||
x = 0
|
||||
for j in range(cols):
|
||||
self.newCell(x, y, width, height, tableId, i, j)
|
||||
x += width
|
||||
y += height
|
||||
|
||||
def getTree(self, id):
|
||||
ids = [id]
|
||||
el = self.svg.getElementById(id)
|
||||
for _el in list(el):
|
||||
for _id in self.getTree(_el.attrib['id']):
|
||||
ids.append(_id)
|
||||
return ids
|
||||
|
||||
|
||||
def getSubSelectedIds(self):
|
||||
ids = []
|
||||
for id in self.svg.selected.ids:
|
||||
for _id in self.getTree(id):
|
||||
ids.append(_id)
|
||||
return ids
|
||||
|
||||
def getAllTables(self):
|
||||
ids = self.getSubSelectedIds()
|
||||
for id in ids:
|
||||
el = self.svg.getElementById(id)
|
||||
if (self.isTableCell(id)):
|
||||
tableId = el.attrib[inkex.addNS('table-id', 'inkex')]
|
||||
if (not self.isset(self.selectedTables, tableId)):
|
||||
self.getTable(tableId)
|
||||
self.tablesTexts[tableId] = self.getTableText(tableId)
|
||||
|
||||
def getTableDimensions(self, tableId):
|
||||
nodes = self.tables.xpath('//inkex:table[@table-id="' + tableId + '"]', namespaces = inkex.NSS)
|
||||
if (len(nodes) > 0):
|
||||
return {'rows': int(nodes[0].attrib['rows']), 'cols': int(nodes[0].attrib['columns'])}
|
||||
return False
|
||||
|
||||
def setTableDimensions(self, tableId, dimensions):
|
||||
table_dim = self.tables.xpath('//inkex:table[@table-id="' + tableId + '"]', namespaces = inkex.NSS)
|
||||
if (len(table_dim) > 0):
|
||||
table_dim[0].set('rows', str(dimensions['rows']))
|
||||
table_dim[0].set('columns', str(dimensions['cols']))
|
||||
|
||||
|
||||
def getTable(self, tableId):
|
||||
nodes = self.tables.xpath('//inkex:table[@table-id="' + tableId + '"]', namespaces = inkex.NSS)
|
||||
if (len(nodes) > 0):
|
||||
cols = int(nodes[0].attrib['columns'])
|
||||
rows = int(nodes[0].attrib['rows'])
|
||||
table = [[None for i in range(cols)] for j in range(rows)]
|
||||
path = '//*[@inkex:table-id="' + tableId + '"]'
|
||||
cells = self.document.xpath(path, namespaces = inkex.NSS)
|
||||
for cell in cells:
|
||||
i = int(cell.attrib[inkex.addNS('row', 'inkex')])
|
||||
j = int(cell.attrib[inkex.addNS('column', 'inkex')])
|
||||
table[i][j] = cell.attrib['id']
|
||||
self.selectedTables[tableId] = table
|
||||
|
||||
def getTableText(self, tableId):
|
||||
nodes = self.tables.xpath('//inkex:table[@table-id="' + tableId + '"]', namespaces = inkex.NSS)
|
||||
if (len(nodes) > 0):
|
||||
cols = int(nodes[0].attrib['columns'])
|
||||
rows = int(nodes[0].attrib['rows'])
|
||||
texts = [[None for i in range(cols)] for j in range(rows)]
|
||||
path = '//*[@inkex:table-id="' + tableId + '-text"]'
|
||||
cells = self.document.xpath(path, namespaces = inkex.NSS)
|
||||
for cell in cells:
|
||||
i = int(cell.attrib[inkex.addNS('row', 'inkex')])
|
||||
j = int(cell.attrib[inkex.addNS('column', 'inkex')])
|
||||
texts[i][j] = cell.attrib['id']
|
||||
return texts
|
||||
return None
|
||||
|
||||
def doAddGuide(self, el, type):
|
||||
px = self.sizeToPx(str(self.svg.unittouu(self.document.getroot().attrib['height'])), 'y')
|
||||
|
||||
position = self.getPosition(el)
|
||||
if (position != False):
|
||||
c = position['coordinates']
|
||||
a = position['matrix']
|
||||
x = c[0]
|
||||
y = c[1]
|
||||
angle = math.acos(a[0][0]) * 180 / math.pi
|
||||
if angle < 90:
|
||||
angle = 90 - angle
|
||||
elif angle < 180:
|
||||
angle = 180 - angle
|
||||
elif angle < 270:
|
||||
angle = 270 - angle
|
||||
else:
|
||||
angle = 360 - angle
|
||||
if (type == self.cell_type_row):
|
||||
angle += 90
|
||||
self.svg.namedview.add(Guide().move_to(str(x), str(px - y), angle))
|
||||
|
||||
def _addGuides(self, tableId, type):
|
||||
table = self.selectedTables[tableId]
|
||||
|
||||
count = len(table)
|
||||
if (type == self.cell_type_column):
|
||||
count = len(table[0])
|
||||
|
||||
for i in range(count):
|
||||
_i = i
|
||||
_j = 0
|
||||
if (type == self.cell_type_column):
|
||||
_i = 0
|
||||
_j = i
|
||||
el = self.svg.getElementById(table[_i][_j])
|
||||
self.doAddGuide(el, type)
|
||||
|
||||
if (i == count - 1):
|
||||
if (type == self.cell_type_column):
|
||||
el.attrib['x'] = str(self.sizeToPx(el.attrib['x'], 'x') + self.sizeToPx(el.attrib['width'], 'x'))
|
||||
else:
|
||||
el.attrib['y'] = str(self.sizeToPx(el.attrib['y'], 'y') + self.sizeToPx(el.attrib['height'], 'y'))
|
||||
self.doAddGuide(el, type)
|
||||
if (type == self.cell_type_column):
|
||||
el.attrib['x'] = str(self.sizeToPx(el.attrib['x'], 'x') - self.sizeToPx(el.attrib['width'], 'x'))
|
||||
else:
|
||||
el.attrib['y'] = str(self.sizeToPx(el.attrib['y'], 'y') - self.sizeToPx(el.attrib['height'], 'y'))
|
||||
|
||||
def addGuides(self, type):
|
||||
for tableId in self.selectedTables:
|
||||
self._addGuides(tableId, type)
|
||||
|
||||
def doEditText(self, id, fontSize):
|
||||
el = self.svg.getElementById(id)
|
||||
if (not self.isTableCell(id)):
|
||||
return
|
||||
|
||||
position = self.getPosition(el)
|
||||
if (position != False):
|
||||
a = position['matrix']
|
||||
if (not self.isUnitMatrix(a)):
|
||||
transform = 'transform="' + self.matrix2string(a) + '"'
|
||||
else:
|
||||
transform = ''
|
||||
content = '<flowRoot id="' + self.svg.get_unique_id(el.attrib[inkex.addNS('table-id', 'inkex')]) + '" xmlns:inkex="http://sodipodi.sourceforge.net/DTD/inkex-0.dtd" ' + transform + ' \
|
||||
inkex:table-id="' + el.attrib[inkex.addNS('table-id', 'inkex')] + '-text" inkex:row="' + el.attrib[inkex.addNS('row', 'inkex')] + '" inkex:column="' + el.attrib[inkex.addNS('column', 'inkex')] + '" \
|
||||
style="font-size:' + fontSize + ';font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;text-align:start;line-height:125%;letter-spacing:0px;word-spacing:0px;text-anchor:start;fill:#000000;fill-opacity:1;stroke:none;font-family:Sans;-inkscape-font-specification:Sans"\
|
||||
xml:space="preserve"><flowRegion id="' + self.svg.get_unique_id(el.attrib[inkex.addNS('table-id', 'inkex')]) + '"><rect id="' + self.svg.get_unique_id(el.attrib[inkex.addNS('table-id', 'inkex')]) + '" style="font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;text-align:start;text-anchor:start;font-family:Sans;-inkscape-font-specification:Sans"\
|
||||
x="' + el.attrib['x'] + '"\
|
||||
y="' + el.attrib['y'] + '"\
|
||||
width="' + el.attrib['width'] + '"\
|
||||
height="' + el.attrib['height'] + '"/></flowRegion><flowPara id="' + self.svg.get_unique_id(el.attrib[inkex.addNS('table-id', 'inkex')]) + '">text here</flowPara></flowRoot>'
|
||||
|
||||
self.svg.get_current_layer().append(etree.fromstring(content))
|
||||
|
||||
def editText(self, fontSize):
|
||||
ids = self.getSubSelectedIds()
|
||||
|
||||
for id in ids:
|
||||
self.doEditText(id, fontSize)
|
||||
|
||||
def getColumnIndex(self, id):
|
||||
el = self.svg.getElementById(id)
|
||||
if (self.isset(el.attrib, inkex.addNS('column', 'inkex'))):
|
||||
return int(el.attrib[inkex.addNS('column', 'inkex')])
|
||||
|
||||
return -1
|
||||
|
||||
def getRowIndex(self, id):
|
||||
el = self.svg.getElementById(id)
|
||||
if (self.isset(el.attrib, inkex.addNS('row', 'inkex'))):
|
||||
return int(el.attrib[inkex.addNS('row', 'inkex')])
|
||||
|
||||
return -1
|
||||
|
||||
def setTextRect(self, text, c):
|
||||
for child in list(text):
|
||||
if (child.tag == inkex.addNS('flowRegion', 'svg')):
|
||||
for subchild in list(child):
|
||||
if (subchild.tag == inkex.addNS('rect', 'svg')):
|
||||
for key, value in c.items():
|
||||
if value != None:
|
||||
subchild.set(key, str(value))
|
||||
break
|
||||
|
||||
def getTextRect(self, text):
|
||||
for child in list(text):
|
||||
if (child.tag == inkex.addNS('flowRegion', 'svg')):
|
||||
for subchild in list(child):
|
||||
if (subchild.tag == inkex.addNS('rect', 'svg')):
|
||||
return subchild
|
||||
|
||||
return None
|
||||
|
||||
def moveCells(self, tableId, idx, delta, type):
|
||||
table = self.selectedTables[tableId]
|
||||
texts = self.tablesTexts[tableId]
|
||||
if (type == self.cell_type_column):
|
||||
starti = 0
|
||||
startj = idx
|
||||
else:
|
||||
starti = idx
|
||||
startj = 0
|
||||
|
||||
for i in range(starti, len(table)):
|
||||
for j in range(startj, len(table[i])):
|
||||
el = self.svg.getElementById(table[i][j])
|
||||
position = self.getPosition(el)
|
||||
if (position != False):
|
||||
c = [self.sizeToPx(el.attrib['x'], 'x'), self.sizeToPx(el.attrib['y'], 'y')]
|
||||
c[0] += delta[0]
|
||||
c[1] += delta[1]
|
||||
el.set('x', str(c[0]))
|
||||
el.set('y', str(c[1]))
|
||||
if (texts != None):
|
||||
if (texts[i][j] != None):
|
||||
el = self.svg.getElementById(texts[i][j])
|
||||
rect = self.getTextRect(el)
|
||||
if (rect != None):
|
||||
c[0] = self.sizeToPx(rect.attrib['x'], 'x') + delta[0]
|
||||
c[1] = self.sizeToPx(rect.attrib['y'], 'y') + delta[1]
|
||||
self.setTextRect(el, {'x': c[0], 'y': c[1]})
|
||||
|
||||
def setCellSize(self, tableId, idx, size, type):
|
||||
table = self.selectedTables[tableId]
|
||||
texts = self.tablesTexts[tableId]
|
||||
if (type == self.cell_type_column):
|
||||
size = self.sizeToPx(size, 'x')
|
||||
old_size = self.sizeToPx(self.svg.getElementById(table[0][idx]).attrib['width'], 'x')
|
||||
else:
|
||||
size = self.sizeToPx(size, 'y')
|
||||
old_size = self.sizeToPx(self.svg.getElementById(table[idx][0]).attrib['height'], 'y')
|
||||
|
||||
if (type == self.cell_type_column):
|
||||
delta = [size - old_size, 0, 1]
|
||||
else:
|
||||
delta = [0, size - old_size, 1]
|
||||
|
||||
if ((idx + 1 < len(table) and type == self.cell_type_row) or (idx + 1 < len(table[0]) and type == self.cell_type_column)):
|
||||
self.moveCells(tableId, idx + 1, delta, type)
|
||||
|
||||
count = len(table[idx])
|
||||
if (type == self.cell_type_column):
|
||||
count = len(table)
|
||||
|
||||
for i in range(count):
|
||||
_i = idx
|
||||
_j = i
|
||||
if type == self.cell_type_column:
|
||||
_i = i
|
||||
_j = idx
|
||||
el = self.svg.getElementById(table[_i][_j])
|
||||
param = 'height'
|
||||
if (type == self.cell_type_column):
|
||||
param = 'width'
|
||||
|
||||
el.set(param, str(size))
|
||||
|
||||
if texts != None:
|
||||
if texts[_i][_j] != None:
|
||||
el = self.svg.getElementById(texts[_i][_j])
|
||||
self.setTextRect(el, {param: size})
|
||||
|
||||
def editSize(self, size, type):
|
||||
processed = {}
|
||||
for node in self.svg.selected.values():
|
||||
id = node.get('id')
|
||||
if (self.isTableCell(id)):
|
||||
tableId = node.attrib[inkex.addNS('table-id', 'inkex')]
|
||||
if (type == self.cell_type_column):
|
||||
idx = self.getColumnIndex(id)
|
||||
else:
|
||||
idx = self.getRowIndex(id)
|
||||
if (not self.isset(processed, tableId)):
|
||||
processed[tableId] = []
|
||||
|
||||
if (not self.isset(processed[tableId], idx)):
|
||||
self.setCellSize(tableId, idx, size, type)
|
||||
processed[tableId].append(idx)
|
||||
|
||||
def getTableWidth(self, tableId):
|
||||
table = self.selectedTables[tableId]
|
||||
width = 0
|
||||
for i in range(len(table[0])):
|
||||
el = self.svg.getElementById(table[0][i])
|
||||
width += self.sizeToPx(el.attrib['width'], 'x')
|
||||
|
||||
return width
|
||||
|
||||
def getTableHeight(self, tableId):
|
||||
table = self.selectedTables[tableId]
|
||||
height = 0
|
||||
for i in range(len(table)):
|
||||
el = self.svg.getElementById(table[i][0])
|
||||
height += self.sizeToPx(el.attrib['height'], 'y')
|
||||
|
||||
return height
|
||||
|
||||
def setTableSize(self, tableId, size, type):
|
||||
if (type == self.cell_type_column):
|
||||
size = self.sizeToPx(size, 'x')
|
||||
old_size = self.getTableWidth(tableId)
|
||||
else:
|
||||
size = self.sizeToPx(size, 'y')
|
||||
old_size = self.getTableHeight(tableId)
|
||||
|
||||
factor = size / old_size
|
||||
table = self.selectedTables[tableId]
|
||||
count = len(table)
|
||||
if (type == self.cell_type_column):
|
||||
count = len(table[0])
|
||||
|
||||
for i in range(count):
|
||||
if (type == self.cell_type_column):
|
||||
el = self.svg.getElementById(table[0][i])
|
||||
new_size = self.sizeToPx(el.attrib['width'], 'x') * factor
|
||||
else:
|
||||
el = self.svg.getElementById(table[i][0])
|
||||
new_size = self.sizeToPx(el.attrib['height'], 'y') * factor
|
||||
self.setCellSize(tableId, i, str(new_size), type)
|
||||
|
||||
def editTable(self, width, height):
|
||||
for id in self.selectedTables:
|
||||
self.setTableSize(id, width, self.cell_type_column)
|
||||
self.setTableSize(id, height, self.cell_type_row)
|
||||
|
||||
def getTablePosition(self, tableId):
|
||||
table = self.selectedTables[tableId]
|
||||
el = self.svg.getElementById(table[0][0])
|
||||
return self.getPosition(el)
|
||||
|
||||
def fitPage(self):
|
||||
width = str(self.svg.unittouu(self.document.getroot().attrib['width']))
|
||||
height = str(self.svg.unittouu(self.document.getroot().attrib['height']))
|
||||
|
||||
for id in self.selectedTables:
|
||||
position = self.getTablePosition(id)
|
||||
if (position != False):
|
||||
c = position['coordinates']
|
||||
self.moveCells(id, 0, [-c[0], -c[1], 1], type)
|
||||
self.setTableSize(id, width, self.cell_type_column)
|
||||
self.setTableSize(id, height, self.cell_type_row)
|
||||
|
||||
def fitPageWidth(self):
|
||||
width = str(self.svg.unittouu(self.document.getroot().attrib['width']))
|
||||
|
||||
for id in self.selectedTables:
|
||||
position = self.getTablePosition(id)
|
||||
if (position != False):
|
||||
c = position['coordinates']
|
||||
self.moveCells(id, 0, [-c[0], 0, 1], type)
|
||||
self.setTableSize(id, width, self.cell_type_column)
|
||||
|
||||
def fitPageHeight(self):
|
||||
height = str(self.svg.unittouu(self.document.getroot().attrib['height']))
|
||||
|
||||
for id in self.selectedTables:
|
||||
position = self.getTablePosition(id)
|
||||
if (position != False):
|
||||
c = position['coordinates']
|
||||
self.moveCells(id, 0, [0, -c[1], 1], type)
|
||||
self.setTableSize(id, height, self.cell_type_row)
|
||||
|
||||
def getSelectedListIds(self):
|
||||
idList = []
|
||||
for id in self.getSubSelectedIds():
|
||||
idList.append(id)
|
||||
return idList
|
||||
|
||||
def getCellText(self, tableId, i, j):
|
||||
texts = self.tablesTexts[tableId]
|
||||
if (texts != None):
|
||||
if (texts[i][j] != None):
|
||||
return self.svg.getElementById(texts[i][j])
|
||||
return None
|
||||
|
||||
def getMergePoints(self, tableId):
|
||||
dim = self.getTableDimensions(tableId)
|
||||
table = self.selectedTables[tableId]
|
||||
idList = self.getSelectedListIds()
|
||||
start = []
|
||||
for i in range(dim['rows']):
|
||||
for j in range(dim['cols']):
|
||||
if (idList.count(table[i][j]) > 0):
|
||||
start = [i, j]
|
||||
break
|
||||
if len(start) > 0:
|
||||
break
|
||||
|
||||
if (len(start) != 2):
|
||||
return False
|
||||
|
||||
end = [1, 1]
|
||||
|
||||
for i in range(start[0] + 1, len(table)):
|
||||
if (idList.count(table[i][start[1]]) > 0):
|
||||
end[0] += 1
|
||||
else:
|
||||
break
|
||||
|
||||
for i in range(start[1] + 1, len(table[0])):
|
||||
if (idList.count(table[start[0]][i]) > 0):
|
||||
end[1] += 1
|
||||
else:
|
||||
break
|
||||
|
||||
for i in range(start[0], start[0] + end[0]):
|
||||
for j in range(start[1], start[1] + end[1]):
|
||||
if (idList.count(table[i][j]) == 0):
|
||||
return False
|
||||
|
||||
return {'i': start[0], 'j': start[1], 'rows': end[0], 'cols': end[1]}
|
||||
|
||||
def mergeTable(self, tableId, points = None):
|
||||
if (points == None):
|
||||
points = self.getMergePoints(tableId)
|
||||
if (points == False):
|
||||
inkex.errormsg('You have to select the cells to form a rectangle from a single table.')
|
||||
return
|
||||
|
||||
table = self.selectedTables[tableId]
|
||||
cell = self.svg.getElementById(table[points['i']][points['j']])
|
||||
width = 0
|
||||
height = 0
|
||||
widths = ''
|
||||
heights = ''
|
||||
|
||||
for i in range(points['i'], points['i'] + points['rows']):
|
||||
el = self.svg.getElementById(table[i][points['j']])
|
||||
height += self.sizeToPx(el.attrib['height'], 'y')
|
||||
if (heights != ''):
|
||||
heights += self.delimiter
|
||||
heights += el.attrib['height']
|
||||
|
||||
for j in range(points['j'], points['j'] + points['cols']):
|
||||
el = self.svg.getElementById(table[points['i']][j])
|
||||
width += self.sizeToPx(el.attrib['width'], 'x')
|
||||
if (widths != ''):
|
||||
widths += self.delimiter
|
||||
widths += el.attrib['width']
|
||||
|
||||
for i in range(points['i'], points['i'] + points['rows']):
|
||||
for j in range(points['j'], points['j'] + points['cols']):
|
||||
if (i != points['i'] or j != points['j']):
|
||||
el = self.svg.getElementById(table[i][j])
|
||||
el.getparent().remove(el)
|
||||
text = self.getCellText(tableId, i, j)
|
||||
if (text != None):
|
||||
text.getparent().remove(text)
|
||||
|
||||
cell.set('width', str(width) + 'px')
|
||||
cell.set('height', str(height) + 'px')
|
||||
cell.set(inkex.addNS('merged', 'inkex'), str(points['rows']) + self.delimiter + str(points['cols']))
|
||||
cell.set(inkex.addNS('merged-columns-widths', 'inkex'), widths)
|
||||
cell.set(inkex.addNS('merged-rows-heights', 'inkex'), heights)
|
||||
|
||||
text = self.getCellText(tableId, points['i'], points['j'])
|
||||
|
||||
if (text != None):
|
||||
rect = self.getTextRect(text)
|
||||
rect.set('width', str(width) + 'px')
|
||||
rect.set('height', str(height) + 'px')
|
||||
|
||||
|
||||
def mergeMerge(self):
|
||||
for id in self.selectedTables:
|
||||
self.mergeTable(id)
|
||||
|
||||
def splitCell(self, cellId):
|
||||
cell = self.svg.getElementById(cellId)
|
||||
if (self.isset(cell.attrib, inkex.addNS('merged', 'inkex'))):
|
||||
tableId = cell.attrib[inkex.addNS('table-id', 'inkex')]
|
||||
row = int(cell.attrib[inkex.addNS('row', 'inkex')])
|
||||
column = int(cell.attrib[inkex.addNS('column', 'inkex')])
|
||||
position = self.getPosition(cell)
|
||||
|
||||
merge_size = cell.attrib[inkex.addNS('merged', 'inkex')].split(self.delimiter)
|
||||
widths = cell.attrib[inkex.addNS('merged-columns-widths', 'inkex')].split(self.delimiter)
|
||||
heights = cell.attrib[inkex.addNS('merged-rows-heights', 'inkex')].split(self.delimiter)
|
||||
|
||||
y = self.sizeToPx(cell.attrib['y'], 'y')
|
||||
|
||||
for i in range(row, row + int(merge_size[0])):
|
||||
x = self.sizeToPx(cell.attrib['x'], 'x')
|
||||
for j in range(column, column + int(merge_size[1])):
|
||||
if (i != row or j != column):
|
||||
transform = None
|
||||
if position != False:
|
||||
a = position['matrix']
|
||||
if (not self.isUnitMatrix(a)):
|
||||
transform = self.matrix2string(a)
|
||||
self.newCell(x, y, self.sizeToPx(widths[j - column], 'x'), self.sizeToPx(heights[i - row], 'y'), tableId, i, j, transform)
|
||||
x += self.sizeToPx(widths[j - column], 'x')
|
||||
y += self.sizeToPx(heights[i - row], 'y')
|
||||
|
||||
result = {'i': row, 'j': column, 'rows': int(merge_size[0]), 'cols': int(merge_size[1])}
|
||||
cell.set('width', widths[0])
|
||||
cell.set('height', heights[0])
|
||||
text = self.getCellText(tableId, row, column)
|
||||
if (text != None):
|
||||
rect = self.getTextRect(text)
|
||||
rect.set('width', widths[0])
|
||||
rect.set('height', heights[0])
|
||||
del cell.attrib[inkex.addNS('merged', 'inkex')]
|
||||
del cell.attrib[inkex.addNS('merged-columns-widths', 'inkex')]
|
||||
del cell.attrib[inkex.addNS('merged-rows-heights', 'inkex')]
|
||||
|
||||
return result
|
||||
return False
|
||||
|
||||
def mergeSplit(self):
|
||||
for id in self.svg.selected.ids:
|
||||
self.splitCell(id)
|
||||
|
||||
def updateMergedPoints(self, tableId, idx, delta, type):
|
||||
if (self.get_tables):
|
||||
if (self.auto_split):
|
||||
if (self.isset(self.mergedCells, tableId)):
|
||||
for points in self.mergedCells[tableId]:
|
||||
cond1 = idx > points['i'] and idx < points['i'] + points['rows']
|
||||
cond2 = idx <= points['i']
|
||||
if (type == self.cell_type_column):
|
||||
cond1 = idx > points['j'] and idx < points['j'] + points['cols']
|
||||
cond2 = idx <= points['j']
|
||||
|
||||
if (cond1):
|
||||
if (type == self.cell_type_column):
|
||||
points['cols'] += delta
|
||||
if (points['cols'] <= 1):
|
||||
points['removed'] = 1
|
||||
else:
|
||||
points['rows'] += delta
|
||||
if (points['rows'] <= 1):
|
||||
points['removed'] = 1
|
||||
elif (cond2):
|
||||
if (type == self.cell_type_column):
|
||||
if (delta == -1 and idx == points['j']):
|
||||
points['cols'] += delta
|
||||
if (points['cols'] <= 1):
|
||||
points['removed'] = 1
|
||||
else:
|
||||
points['j'] += delta
|
||||
else:
|
||||
if (delta == -1 and idx == points['i']):
|
||||
points['rows'] += delta
|
||||
if (points['rows'] <= 1):
|
||||
points['removed'] = 1
|
||||
else:
|
||||
points['i'] += delta
|
||||
|
||||
def incrementCoordonate(self, tableId, idx, inc, type):
|
||||
table = self.selectedTables[tableId]
|
||||
texts = self.getTableText(tableId)
|
||||
starti = idx
|
||||
startj = 0
|
||||
dim = self.getTableDimensions(tableId)
|
||||
if type == self.cell_type_column:
|
||||
dim['cols'] += inc
|
||||
else:
|
||||
dim['rows'] += inc
|
||||
self.setTableDimensions(tableId, dim)
|
||||
|
||||
if (type == self.cell_type_column):
|
||||
starti = 0
|
||||
startj = idx
|
||||
|
||||
for i in range(starti, len(table)):
|
||||
for j in range(startj, len(table[i])):
|
||||
cell = self.svg.getElementById(table[i][j])
|
||||
text = self.svg.getElementById(texts[i][j])
|
||||
if (type == self.cell_type_column):
|
||||
cell.set(inkex.addNS('column', 'inkex'), str(int(cell.attrib[inkex.addNS('column', 'inkex')]) + inc))
|
||||
if (text != None):
|
||||
text.set(inkex.addNS('column', 'inkex'), str(int(text.attrib[inkex.addNS('column', 'inkex')]) + inc))
|
||||
else:
|
||||
cell.set(inkex.addNS('row', 'inkex'), str(int(cell.attrib[inkex.addNS('row', 'inkex')]) + inc))
|
||||
if (text != None):
|
||||
text.set(inkex.addNS('row', 'inkex'), str(int(text.attrib[inkex.addNS('row', 'inkex')]) + inc))
|
||||
|
||||
def addCell(self, tableId, idx, type):
|
||||
table = self.selectedTables[tableId]
|
||||
if (type == self.cell_type_column):
|
||||
if (idx != -1):
|
||||
delta = [self.sizeToPx(self.svg.getElementById(table[0][idx]).attrib['width'], 'x'), 0, 1]
|
||||
else:
|
||||
delta = [self.sizeToPx(self.svg.getElementById(table[0][0]).attrib['width'], 'x'), 0, 1]
|
||||
else:
|
||||
if (idx != -1):
|
||||
delta = [0, self.sizeToPx(self.svg.getElementById(table[idx][0]).attrib['height'], 'y'), 1]
|
||||
else:
|
||||
delta = [0, self.sizeToPx(self.svg.getElementById(table[0][0]).attrib['height'], 'y'), 1]
|
||||
|
||||
count = len(table)
|
||||
if type == self.cell_type_row:
|
||||
if (idx != -1):
|
||||
count = len(table[idx])
|
||||
else:
|
||||
count = len(table[0])
|
||||
for i in range(count):
|
||||
if (type == self.cell_type_column):
|
||||
if (idx != -1):
|
||||
cell = self.svg.getElementById(table[i][idx])
|
||||
else:
|
||||
cell = self.svg.getElementById(table[i][0])
|
||||
else:
|
||||
if (idx != -1):
|
||||
cell = self.svg.getElementById(table[idx][i])
|
||||
else:
|
||||
cell = self.svg.getElementById(table[0][i])
|
||||
|
||||
position = self.getPosition(cell)
|
||||
transform = ''
|
||||
if (position != False):
|
||||
a = position['matrix']
|
||||
if (not self.isUnitMatrix(a)):
|
||||
transform = self.matrix2string(a)
|
||||
x = self.sizeToPx(cell.attrib['x'], 'x')
|
||||
y = self.sizeToPx(cell.attrib['y'], 'y')
|
||||
width = self.sizeToPx(cell.attrib['width'], 'x')
|
||||
height = self.sizeToPx(cell.attrib['height'], 'y')
|
||||
|
||||
if (type == self.cell_type_column):
|
||||
if (idx != -1):
|
||||
x += width
|
||||
self.newCell(x, y, width, height, tableId, i, idx + 1, transform)
|
||||
else:
|
||||
if (idx != -1):
|
||||
y += height
|
||||
self.newCell(x, y, width, height, tableId, idx + 1, i, transform)
|
||||
|
||||
self.moveCells(tableId, idx + 1, delta, type)
|
||||
self.updateMergedPoints(tableId, idx + 1, 1, type)
|
||||
self.incrementCoordonate(tableId, idx + 1, 1, type)
|
||||
self.getTable(tableId)
|
||||
self.tablesTexts[tableId] = self.getTableText(tableId)
|
||||
|
||||
def addColumns(self, count, where):
|
||||
for id in self.svg.selected.ids:
|
||||
el = self.svg.getElementById(id)
|
||||
if (self.isTableCell(id)):
|
||||
tableId = el.attrib[inkex.addNS('table-id', 'inkex')]
|
||||
idx = self.getColumnIndex(id)
|
||||
if (where == 'before'):
|
||||
idx -= 1
|
||||
|
||||
for i in range(count):
|
||||
self.addCell(tableId, idx, self.cell_type_column)
|
||||
|
||||
def addRows(self, count, where):
|
||||
for id in self.svg.selected.ids:
|
||||
el = self.svg.getElementById(id)
|
||||
if (self.isTableCell(id)):
|
||||
tableId = el.attrib[inkex.addNS('table-id', 'inkex')]
|
||||
idx = self.getRowIndex(id)
|
||||
if (where == 'before'):
|
||||
idx -= 1
|
||||
|
||||
for i in range(count):
|
||||
self.addCell(tableId, idx, self.cell_type_row)
|
||||
|
||||
break
|
||||
|
||||
def removeCell(self, tableId, idx, type):
|
||||
table = self.selectedTables[tableId]
|
||||
texts = self.tablesTexts[tableId]
|
||||
if (type == self.cell_type_column):
|
||||
delta = [-self.sizeToPx(self.svg.getElementById(table[0][idx]).attrib['width'], 'x'), 0, 1]
|
||||
else:
|
||||
delta = [0, -self.sizeToPx(self.svg.getElementById(table[idx][0]).attrib['height'], 'y'), 1]
|
||||
|
||||
count = len(table)
|
||||
if type == self.cell_type_row:
|
||||
count = len(table[idx])
|
||||
|
||||
for i in range(count):
|
||||
if (type == self.cell_type_column):
|
||||
cell = self.svg.getElementById(table[i][idx])
|
||||
text = self.svg.getElementById(texts[i][idx])
|
||||
else:
|
||||
cell = self.svg.getElementById(table[idx][i])
|
||||
text = self.svg.getElementById(texts[idx][i])
|
||||
|
||||
if (cell != None):
|
||||
cell.getparent().remove(cell)
|
||||
if (text != None):
|
||||
text.getparent().remove(text)
|
||||
|
||||
self.moveCells(tableId, idx + 1, delta, type)
|
||||
self.updateMergedPoints(tableId, idx, -1, type)
|
||||
self.incrementCoordonate(tableId, idx + 1, -1, type)
|
||||
self.getTable(tableId)
|
||||
self.tablesTexts[tableId] = self.getTableText(tableId)
|
||||
|
||||
def removeRowsColumns(self, type):
|
||||
for id in self.svg.selected.ids:
|
||||
el = self.svg.getElementById(id)
|
||||
if (el != None):
|
||||
if (self.isTableCell(id)):
|
||||
tableId = el.attrib[inkex.addNS('table-id', 'inkex')]
|
||||
if (type == self.cell_type_column):
|
||||
idx = self.getColumnIndex(id)
|
||||
else:
|
||||
idx = self.getRowIndex(id)
|
||||
|
||||
self.removeCell(tableId, idx, type)
|
@ -0,0 +1,23 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<inkscape-extension xmlns="http://www.inkscape.org/namespace/inkscape/extension">
|
||||
<name>Columns</name>
|
||||
<id>fablabchemnitz.de.table_add_columns</id>
|
||||
<param name="number" type="int" gui-text="The number of columns to add:">1</param>
|
||||
<param name="where" type="optiongroup" appearance="radio" gui-text="Before or after the selected column:">
|
||||
<option value="before">Before</option>
|
||||
<option value="after">After</option>
|
||||
</param>
|
||||
<effect>
|
||||
<object-type>all</object-type>
|
||||
<effects-menu>
|
||||
<submenu name="FabLab Chemnitz">
|
||||
<submenu name="Table">
|
||||
<submenu name="Add" />
|
||||
</submenu>
|
||||
</submenu>
|
||||
</effects-menu>
|
||||
</effect>
|
||||
<script>
|
||||
<command location="inx" interpreter="python">table_add_columns.py</command>
|
||||
</script>
|
||||
</inkscape-extension>
|
34
extensions/fablabchemnitz/table_support/table_add_columns.py
Executable file
34
extensions/fablabchemnitz/table_support/table_add_columns.py
Executable file
@ -0,0 +1,34 @@
|
||||
#!/usr/bin/env python3
|
||||
"""
|
||||
table.py
|
||||
Table support for Inkscape
|
||||
|
||||
Copyright (C) 2011 Cosmin Popescu, cosminadrianpopescu@gmail.com
|
||||
|
||||
This program is free software; you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as published by
|
||||
the Free Software Foundation; either version 2 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 General Public License for more details.
|
||||
"""
|
||||
import sys
|
||||
import os
|
||||
import table
|
||||
|
||||
sys.path.append(os.path.dirname(sys.argv[0]))
|
||||
|
||||
class Table(table.TableEngine):
|
||||
def __init__(self):
|
||||
table.TableEngine.__init__(self, True, True)
|
||||
self.arg_parser.add_argument('--number', type = int, default = 1, help = 'The number of columns')
|
||||
self.arg_parser.add_argument('--where', default = "after", help = 'Where to add')
|
||||
|
||||
def doinkex(self):
|
||||
self.addColumns(self.options.number, self.options.where)
|
||||
|
||||
if __name__ == '__main__': #pragma: no cover
|
||||
Table().run()
|
18
extensions/fablabchemnitz/table_support/table_add_guides.inx
Normal file
18
extensions/fablabchemnitz/table_support/table_add_guides.inx
Normal file
@ -0,0 +1,18 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<inkscape-extension xmlns="http://www.inkscape.org/namespace/inkscape/extension">
|
||||
<name>Guide Lines</name>
|
||||
<id>fablabchemnitz.de.table_add_guides</id>
|
||||
<effect>
|
||||
<object-type>all</object-type>
|
||||
<effects-menu>
|
||||
<submenu name="FabLab Chemnitz">
|
||||
<submenu name="Table">
|
||||
<submenu name="Add" />
|
||||
</submenu>
|
||||
</submenu>
|
||||
</effects-menu>
|
||||
</effect>
|
||||
<script>
|
||||
<command location="inx" interpreter="python">table_add_guides.py</command>
|
||||
</script>
|
||||
</inkscape-extension>
|
34
extensions/fablabchemnitz/table_support/table_add_guides.py
Executable file
34
extensions/fablabchemnitz/table_support/table_add_guides.py
Executable file
@ -0,0 +1,34 @@
|
||||
#!/usr/bin/env python3
|
||||
"""
|
||||
table.py
|
||||
Table support for Inkscape
|
||||
|
||||
Copyright (C) 2011 Cosmin Popescu, cosminadrianpopescu@gmail.com
|
||||
|
||||
This program is free software; you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as published by
|
||||
the Free Software Foundation; either version 2 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 General Public License for more details.
|
||||
"""
|
||||
|
||||
import sys
|
||||
import os
|
||||
import table
|
||||
|
||||
sys.path.append(os.path.dirname(sys.argv[0]))
|
||||
|
||||
class Table(table.TableEngine):
|
||||
def __init__(self):
|
||||
table.TableEngine.__init__(self)
|
||||
|
||||
def doinkex(self):
|
||||
self.addGuides(self.cell_type_row)
|
||||
self.addGuides(self.cell_type_column)
|
||||
|
||||
if __name__ == '__main__': #pragma: no cover
|
||||
Table().run()
|
23
extensions/fablabchemnitz/table_support/table_add_rows.inx
Normal file
23
extensions/fablabchemnitz/table_support/table_add_rows.inx
Normal file
@ -0,0 +1,23 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<inkscape-extension xmlns="http://www.inkscape.org/namespace/inkscape/extension">
|
||||
<name>Rows</name>
|
||||
<id>fablabchemnitz.de.table_add_rows</id>
|
||||
<param name="number" type="int" gui-text="The number of rows to add:">1</param>
|
||||
<param name="where" type="optiongroup" appearance="radio" gui-text="Before or after the selected rows:">
|
||||
<option value="before">Before</option>
|
||||
<option value="after">After</option>
|
||||
</param>
|
||||
<effect>
|
||||
<object-type>all</object-type>
|
||||
<effects-menu>
|
||||
<submenu name="FabLab Chemnitz">
|
||||
<submenu name="Table">
|
||||
<submenu name="Add" />
|
||||
</submenu>
|
||||
</submenu>
|
||||
</effects-menu>
|
||||
</effect>
|
||||
<script>
|
||||
<command location="inx" interpreter="python">table_add_rows.py</command>
|
||||
</script>
|
||||
</inkscape-extension>
|
34
extensions/fablabchemnitz/table_support/table_add_rows.py
Executable file
34
extensions/fablabchemnitz/table_support/table_add_rows.py
Executable file
@ -0,0 +1,34 @@
|
||||
#!/usr/bin/env python3
|
||||
"""
|
||||
table.py
|
||||
Table support for Inkscape
|
||||
|
||||
Copyright (C) 2011 Cosmin Popescu, cosminadrianpopescu@gmail.com
|
||||
|
||||
This program is free software; you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as published by
|
||||
the Free Software Foundation; either version 2 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 General Public License for more details.
|
||||
"""
|
||||
import sys
|
||||
import os
|
||||
import table
|
||||
|
||||
sys.path.append(os.path.dirname(sys.argv[0]))
|
||||
|
||||
class Table(table.TableEngine):
|
||||
def __init__(self):
|
||||
table.TableEngine.__init__(self, True, True)
|
||||
self.arg_parser.add_argument('--number', type = int, default = 1, help = 'The number of rows')
|
||||
self.arg_parser.add_argument('--where', default = "after", help = 'Where to add')
|
||||
|
||||
def doinkex(self):
|
||||
self.addRows(self.options.number, self.options.where)
|
||||
|
||||
if __name__ == '__main__': #pragma: no cover
|
||||
Table().run()
|
28
extensions/fablabchemnitz/table_support/table_create.inx
Normal file
28
extensions/fablabchemnitz/table_support/table_create.inx
Normal file
@ -0,0 +1,28 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<inkscape-extension xmlns="http://www.inkscape.org/namespace/inkscape/extension">
|
||||
<name>Create</name>
|
||||
<id>fablabchemnitz.de.table_create</id>
|
||||
<param name="tab" type="notebook">
|
||||
<page name="options" gui-text="Options">
|
||||
<param name="cols" type="int" gui-text="The number of columns:">2</param>
|
||||
<param name="rows" type="int" gui-text="The number of rows:">2</param>
|
||||
<param name="width" type="string" gui-text="The width of the cell:">100mm</param>
|
||||
<param name="height" type="string" gui-text="The height of the cell:">20mm</param>
|
||||
<label>VERY IMPORTANT: You will notice that the newly created table does not contain text. In order to edit any cell's text, just select the cell and then from the Extensions menu select Table -> Edit -> Selected cells text</label>
|
||||
</page>
|
||||
<page name="help" gui-text="Help">
|
||||
<label>This is the first step in using the table support. First create a table. You have to input the number of rows, the number of columns and the width and the height of each cell. The width of the table will equal the number of columns times the width of each cell and the table height will equal the number of rows times the height of each cell. If you want to set a specific width and height for the table, after creating it, you just select it and then select from the Extensions menu -> Table -> Edit -> Table width and height. For the width and height you can also input the measurement unit (mm, cm, in, px etc.). If you don't input any measurement unit, the size will be calculated in pixels. Do not use any space between the value and the unit.</label>
|
||||
</page>
|
||||
</param>
|
||||
<effect>
|
||||
<object-type>all</object-type>
|
||||
<effects-menu>
|
||||
<submenu name="FabLab Chemnitz">
|
||||
<submenu name="Table" />
|
||||
</submenu>
|
||||
</effects-menu>
|
||||
</effect>
|
||||
<script>
|
||||
<command location="inx" interpreter="python">table_create.py</command>
|
||||
</script>
|
||||
</inkscape-extension>
|
38
extensions/fablabchemnitz/table_support/table_create.py
Executable file
38
extensions/fablabchemnitz/table_support/table_create.py
Executable file
@ -0,0 +1,38 @@
|
||||
#!/usr/bin/env python3
|
||||
"""
|
||||
table.py
|
||||
Table support for Inkscape
|
||||
|
||||
Copyright (C) 2011 Cosmin Popescu, cosminadrianpopescu@gmail.com
|
||||
|
||||
This program is free software; you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as published by
|
||||
the Free Software Foundation; either version 2 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 General Public License for more details.
|
||||
"""
|
||||
|
||||
import sys
|
||||
import os
|
||||
import table
|
||||
|
||||
sys.path.append(os.path.dirname(sys.argv[0]))
|
||||
|
||||
class Table(table.TableEngine):
|
||||
|
||||
def add_arguments(self, pars):
|
||||
pars.add_argument("--rows", type=int, default=2, help='The number of table rows')
|
||||
pars.add_argument("--cols", type=int, default=2, help='The number of table columns')
|
||||
pars.add_argument("--width", default='100mm', help='The width of the table')
|
||||
pars.add_argument("--height", default='20mm', help='The height of the table')
|
||||
pars.add_argument("--tab")
|
||||
|
||||
def doinkex(self):
|
||||
self.create(self.options.width, self.options.height, self.options.cols, self.options.rows)
|
||||
|
||||
if __name__ == '__main__': #pragma: no cover
|
||||
Table().run()
|
@ -0,0 +1,20 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<inkscape-extension xmlns="http://www.inkscape.org/namespace/inkscape/extension">
|
||||
<name>Selected columns width</name>
|
||||
<id>fablabchemnitz.de.table_edit_columns</id>
|
||||
<param name="width" type="string" gui-text="Input the new width:">10mm</param>
|
||||
<!--param name="keep" type="bool" gui-text="Keep the table original height">false</param-->
|
||||
<effect>
|
||||
<object-type>all</object-type>
|
||||
<effects-menu>
|
||||
<submenu name="FabLab Chemnitz">
|
||||
<submenu name="Table">
|
||||
<submenu name="Edit" />
|
||||
</submenu>
|
||||
</submenu>
|
||||
</effects-menu>
|
||||
</effect>
|
||||
<script>
|
||||
<command location="inx" interpreter="python">table_edit_columns.py</command>
|
||||
</script>
|
||||
</inkscape-extension>
|
34
extensions/fablabchemnitz/table_support/table_edit_columns.py
Executable file
34
extensions/fablabchemnitz/table_support/table_edit_columns.py
Executable file
@ -0,0 +1,34 @@
|
||||
#!/usr/bin/env python3
|
||||
"""
|
||||
table.py
|
||||
Table support for Inkscape
|
||||
|
||||
Copyright (C) 2011 Cosmin Popescu, cosminadrianpopescu@gmail.com
|
||||
|
||||
This program is free software; you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as published by
|
||||
the Free Software Foundation; either version 2 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 General Public License for more details.
|
||||
"""
|
||||
|
||||
import sys
|
||||
import os
|
||||
import table
|
||||
|
||||
sys.path.append(os.path.dirname(sys.argv[0]))
|
||||
|
||||
class Table(table.TableEngine):
|
||||
|
||||
def add_arguments(self, pars):
|
||||
pars.add_argument("--width", default='10mm', help='The new width')
|
||||
|
||||
def doinkex(self):
|
||||
self.editSize(self.options.width, self.cell_type_column)
|
||||
|
||||
if __name__ == '__main__': #pragma: no cover
|
||||
Table().run()
|
20
extensions/fablabchemnitz/table_support/table_edit_rows.inx
Normal file
20
extensions/fablabchemnitz/table_support/table_edit_rows.inx
Normal file
@ -0,0 +1,20 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<inkscape-extension xmlns="http://www.inkscape.org/namespace/inkscape/extension">
|
||||
<name>Selected rows height</name>
|
||||
<id>fablabchemnitz.de.table_edit_rows</id>
|
||||
<param name="height" type="string" gui-text="Input the new height:">10mm</param>
|
||||
<!--param name="keep" type="bool" gui-text="Keep the table original height">false</param-->
|
||||
<effect>
|
||||
<object-type>all</object-type>
|
||||
<effects-menu>
|
||||
<submenu name="FabLab Chemnitz">
|
||||
<submenu name="Table">
|
||||
<submenu name="Edit" />
|
||||
</submenu>
|
||||
</submenu>
|
||||
</effects-menu>
|
||||
</effect>
|
||||
<script>
|
||||
<command location="inx" interpreter="python">table_edit_rows.py</command>
|
||||
</script>
|
||||
</inkscape-extension>
|
34
extensions/fablabchemnitz/table_support/table_edit_rows.py
Executable file
34
extensions/fablabchemnitz/table_support/table_edit_rows.py
Executable file
@ -0,0 +1,34 @@
|
||||
#!/usr/bin/env python3
|
||||
"""
|
||||
table.py
|
||||
Table support for Inkscape
|
||||
|
||||
Copyright (C) 2011 Cosmin Popescu, cosminadrianpopescu@gmail.com
|
||||
|
||||
This program is free software; you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as published by
|
||||
the Free Software Foundation; either version 2 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 General Public License for more details.
|
||||
"""
|
||||
|
||||
import sys
|
||||
import os
|
||||
import table
|
||||
|
||||
sys.path.append(os.path.dirname(sys.argv[0]))
|
||||
|
||||
class Table(table.TableEngine):
|
||||
|
||||
def add_arguments(self, pars):
|
||||
pars.add_argument("--height", default='10mm', help='The new height')
|
||||
|
||||
def doinkex(self):
|
||||
self.editSize(self.options.height, self.cell_type_row)
|
||||
|
||||
if __name__ == '__main__': #pragma: no cover
|
||||
Table().run()
|
21
extensions/fablabchemnitz/table_support/table_edit_table.inx
Normal file
21
extensions/fablabchemnitz/table_support/table_edit_table.inx
Normal file
@ -0,0 +1,21 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<inkscape-extension xmlns="http://www.inkscape.org/namespace/inkscape/extension">
|
||||
<name>Selected table width and height</name>
|
||||
<id>fablabchemnitz.de.table_edit_table</id>
|
||||
<param name="width" type="string" gui-text="Input the new width of the table:">150mm</param>
|
||||
<param name="height" type="string" gui-text="Input the new height of the table:">60mm</param>
|
||||
<!--param name="keep" type="bool" gui-text="Keep the table original height">false</param-->
|
||||
<effect>
|
||||
<object-type>all</object-type>
|
||||
<effects-menu>
|
||||
<submenu name="FabLab Chemnitz">
|
||||
<submenu name="Table">
|
||||
<submenu name="Edit" />
|
||||
</submenu>
|
||||
</submenu>
|
||||
</effects-menu>
|
||||
</effect>
|
||||
<script>
|
||||
<command location="inx" interpreter="python">table_edit_table.py</command>
|
||||
</script>
|
||||
</inkscape-extension>
|
35
extensions/fablabchemnitz/table_support/table_edit_table.py
Executable file
35
extensions/fablabchemnitz/table_support/table_edit_table.py
Executable file
@ -0,0 +1,35 @@
|
||||
#!/usr/bin/env python3
|
||||
"""
|
||||
table.py
|
||||
Table support for Inkscape
|
||||
|
||||
Copyright (C) 2011 Cosmin Popescu, cosminadrianpopescu@gmail.com
|
||||
|
||||
This program is free software; you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as published by
|
||||
the Free Software Foundation; either version 2 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 General Public License for more details.
|
||||
"""
|
||||
|
||||
import sys
|
||||
import os
|
||||
import table
|
||||
|
||||
sys.path.append(os.path.dirname(sys.argv[0]))
|
||||
|
||||
class Table(table.TableEngine):
|
||||
|
||||
def add_arguments(self, pars):
|
||||
pars.add_argument("--width", default='150mm', help='The new width')
|
||||
pars.add_argument("--height", default='60mm', help='The new height')
|
||||
|
||||
def doinkex(self):
|
||||
self.editTable(self.options.width, self.options.height)
|
||||
|
||||
if __name__ == '__main__': #pragma: no cover
|
||||
Table().run()
|
19
extensions/fablabchemnitz/table_support/table_edit_text.inx
Normal file
19
extensions/fablabchemnitz/table_support/table_edit_text.inx
Normal file
@ -0,0 +1,19 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<inkscape-extension xmlns="http://www.inkscape.org/namespace/inkscape/extension">
|
||||
<name>Selected cells text</name>
|
||||
<id>fablabchemnitz.de.table_edit_text</id>
|
||||
<param name="size" type="string" gui-text="The font size:">12px</param>
|
||||
<effect>
|
||||
<object-type>all</object-type>
|
||||
<effects-menu>
|
||||
<submenu name="FabLab Chemnitz">
|
||||
<submenu name="Table">
|
||||
<submenu name="Edit" />
|
||||
</submenu>
|
||||
</submenu>
|
||||
</effects-menu>
|
||||
</effect>
|
||||
<script>
|
||||
<command location="inx" interpreter="python">table_edit_text.py</command>
|
||||
</script>
|
||||
</inkscape-extension>
|
34
extensions/fablabchemnitz/table_support/table_edit_text.py
Executable file
34
extensions/fablabchemnitz/table_support/table_edit_text.py
Executable file
@ -0,0 +1,34 @@
|
||||
#!/usr/bin/env python3
|
||||
"""
|
||||
table.py
|
||||
Table support for Inkscape
|
||||
|
||||
Copyright (C) 2011 Cosmin Popescu, cosminadrianpopescu@gmail.com
|
||||
|
||||
This program is free software; you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as published by
|
||||
the Free Software Foundation; either version 2 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 General Public License for more details.
|
||||
"""
|
||||
|
||||
import sys
|
||||
import os
|
||||
import table
|
||||
|
||||
sys.path.append(os.path.dirname(sys.argv[0]))
|
||||
|
||||
class Table(table.TableEngine):
|
||||
|
||||
def add_arguments(self, pars):
|
||||
pars.add_argument("--size", default='12px', help='The font size')
|
||||
|
||||
def doinkex(self):
|
||||
self.editText(self.options.size)
|
||||
|
||||
if __name__ == '__main__': #pragma: no cover
|
||||
Table().run()
|
18
extensions/fablabchemnitz/table_support/table_fit_height.inx
Normal file
18
extensions/fablabchemnitz/table_support/table_fit_height.inx
Normal file
@ -0,0 +1,18 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<inkscape-extension xmlns="http://www.inkscape.org/namespace/inkscape/extension">
|
||||
<name>Selected table to page height</name>
|
||||
<id>fablabchemnitz.de.table_fit_height</id>
|
||||
<effect>
|
||||
<object-type>all</object-type>
|
||||
<effects-menu>
|
||||
<submenu name="FabLab Chemnitz">
|
||||
<submenu name="Table">
|
||||
<submenu name="Fit" />
|
||||
</submenu>
|
||||
</submenu>
|
||||
</effects-menu>
|
||||
</effect>
|
||||
<script>
|
||||
<command location="inx" interpreter="python">table_fit_height.py</command>
|
||||
</script>
|
||||
</inkscape-extension>
|
32
extensions/fablabchemnitz/table_support/table_fit_height.py
Normal file
32
extensions/fablabchemnitz/table_support/table_fit_height.py
Normal file
@ -0,0 +1,32 @@
|
||||
#!/usr/bin/env python3
|
||||
"""
|
||||
table.py
|
||||
Table support for Inkscape
|
||||
|
||||
Copyright (C) 2011 Cosmin Popescu, cosminadrianpopescu@gmail.com
|
||||
|
||||
This program is free software; you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as published by
|
||||
the Free Software Foundation; either version 2 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 General Public License for more details.
|
||||
"""
|
||||
import sys
|
||||
import os
|
||||
import table
|
||||
|
||||
sys.path.append(os.path.dirname(sys.argv[0]))
|
||||
|
||||
class Table(table.TableEngine):
|
||||
def __init__(self):
|
||||
table.TableEngine.__init__(self)
|
||||
|
||||
def doinkex(self):
|
||||
self.fitPageHeight()
|
||||
|
||||
if __name__ == '__main__': #pragma: no cover
|
||||
Table().run()
|
18
extensions/fablabchemnitz/table_support/table_fit_page.inx
Normal file
18
extensions/fablabchemnitz/table_support/table_fit_page.inx
Normal file
@ -0,0 +1,18 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<inkscape-extension xmlns="http://www.inkscape.org/namespace/inkscape/extension">
|
||||
<name>Selected table to page</name>
|
||||
<id>fablabchemnitz.de.table_fit_page</id>
|
||||
<effect>
|
||||
<object-type>all</object-type>
|
||||
<effects-menu>
|
||||
<submenu name="FabLab Chemnitz">
|
||||
<submenu name="Table">
|
||||
<submenu name="Fit" />
|
||||
</submenu>
|
||||
</submenu>
|
||||
</effects-menu>
|
||||
</effect>
|
||||
<script>
|
||||
<command location="inx" interpreter="python">table_fit_page.py</command>
|
||||
</script>
|
||||
</inkscape-extension>
|
31
extensions/fablabchemnitz/table_support/table_fit_page.py
Normal file
31
extensions/fablabchemnitz/table_support/table_fit_page.py
Normal file
@ -0,0 +1,31 @@
|
||||
#!/usr/bin/env python3
|
||||
"""
|
||||
table.py
|
||||
Table support for Inkscape
|
||||
|
||||
Copyright (C) 2011 Cosmin Popescu, cosminadrianpopescu@gmail.com
|
||||
|
||||
This program is free software; you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as published by
|
||||
the Free Software Foundation; either version 2 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 General Public License for more details.
|
||||
"""
|
||||
|
||||
import sys
|
||||
import os
|
||||
import table
|
||||
|
||||
sys.path.append(os.path.dirname(sys.argv[0]))
|
||||
|
||||
class Table(table.TableEngine):
|
||||
|
||||
def doinkex(self):
|
||||
self.fitPage()
|
||||
|
||||
if __name__ == '__main__': #pragma: no cover
|
||||
Table().run()
|
18
extensions/fablabchemnitz/table_support/table_fit_width.inx
Normal file
18
extensions/fablabchemnitz/table_support/table_fit_width.inx
Normal file
@ -0,0 +1,18 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<inkscape-extension xmlns="http://www.inkscape.org/namespace/inkscape/extension">
|
||||
<name>Selected table to page width</name>
|
||||
<id>fablabchemnitz.de.table_fit_width</id>
|
||||
<effect>
|
||||
<object-type>all</object-type>
|
||||
<effects-menu>
|
||||
<submenu name="FabLab Chemnitz">
|
||||
<submenu name="Table">
|
||||
<submenu name="Fit" />
|
||||
</submenu>
|
||||
</submenu>
|
||||
</effects-menu>
|
||||
</effect>
|
||||
<script>
|
||||
<command location="inx" interpreter="python">table_fit_width.py</command>
|
||||
</script>
|
||||
</inkscape-extension>
|
32
extensions/fablabchemnitz/table_support/table_fit_width.py
Normal file
32
extensions/fablabchemnitz/table_support/table_fit_width.py
Normal file
@ -0,0 +1,32 @@
|
||||
#!/usr/bin/env python3
|
||||
"""
|
||||
table.py
|
||||
Table support for Inkscape
|
||||
|
||||
Copyright (C) 2011 Cosmin Popescu, cosminadrianpopescu@gmail.com
|
||||
|
||||
This program is free software; you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as published by
|
||||
the Free Software Foundation; either version 2 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 General Public License for more details.
|
||||
"""
|
||||
import sys
|
||||
import os
|
||||
import table
|
||||
|
||||
sys.path.append(os.path.dirname(sys.argv[0]))
|
||||
|
||||
class Table(table.TableEngine):
|
||||
def __init__(self):
|
||||
table.TableEngine.__init__(self)
|
||||
|
||||
def doinkex(self):
|
||||
self.fitPageWidth()
|
||||
|
||||
if __name__ == '__main__': #pragma: no cover
|
||||
Table().run()
|
@ -0,0 +1,18 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<inkscape-extension xmlns="http://www.inkscape.org/namespace/inkscape/extension">
|
||||
<name>Merge selected cells</name>
|
||||
<id>fablabchemnitz.de.table_merge_merge</id>
|
||||
<effect>
|
||||
<object-type>all</object-type>
|
||||
<effects-menu>
|
||||
<submenu name="FabLab Chemnitz">
|
||||
<submenu name="Table">
|
||||
<submenu name="Merge cells" />
|
||||
</submenu>
|
||||
</submenu>
|
||||
</effects-menu>
|
||||
</effect>
|
||||
<script>
|
||||
<command location="inx" interpreter="python">table_merge_merge.py</command>
|
||||
</script>
|
||||
</inkscape-extension>
|
32
extensions/fablabchemnitz/table_support/table_merge_merge.py
Normal file
32
extensions/fablabchemnitz/table_support/table_merge_merge.py
Normal file
@ -0,0 +1,32 @@
|
||||
#!/usr/bin/env python3
|
||||
"""
|
||||
table.py
|
||||
Table support for Inkscape
|
||||
|
||||
Copyright (C) 2011 Cosmin Popescu, cosminadrianpopescu@gmail.com
|
||||
|
||||
This program is free software; you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as published by
|
||||
the Free Software Foundation; either version 2 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 General Public License for more details.
|
||||
"""
|
||||
import sys
|
||||
import os
|
||||
import table
|
||||
|
||||
sys.path.append(os.path.dirname(sys.argv[0]))
|
||||
|
||||
class Table(table.TableEngine):
|
||||
def __init__(self):
|
||||
table.TableEngine.__init__(self)
|
||||
|
||||
def doinkex(self):
|
||||
self.mergeMerge()
|
||||
|
||||
if __name__ == '__main__': #pragma: no cover
|
||||
Table().run()
|
@ -0,0 +1,18 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<inkscape-extension xmlns="http://www.inkscape.org/namespace/inkscape/extension">
|
||||
<name>Split selected cells</name>
|
||||
<id>fablabchemnitz.de.table_merge_split</id>
|
||||
<effect>
|
||||
<object-type>all</object-type>
|
||||
<effects-menu>
|
||||
<submenu name="FabLab Chemnitz">
|
||||
<submenu name="Table">
|
||||
<submenu name="Merge cells" />
|
||||
</submenu>
|
||||
</submenu>
|
||||
</effects-menu>
|
||||
</effect>
|
||||
<script>
|
||||
<command location="inx" interpreter="python">table_merge_split.py</command>
|
||||
</script>
|
||||
</inkscape-extension>
|
32
extensions/fablabchemnitz/table_support/table_merge_split.py
Executable file
32
extensions/fablabchemnitz/table_support/table_merge_split.py
Executable file
@ -0,0 +1,32 @@
|
||||
#!/usr/bin/env python3
|
||||
"""
|
||||
table.py
|
||||
Table support for Inkscape
|
||||
|
||||
Copyright (C) 2011 Cosmin Popescu, cosminadrianpopescu@gmail.com
|
||||
|
||||
This program is free software; you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as published by
|
||||
the Free Software Foundation; either version 2 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 General Public License for more details.
|
||||
"""
|
||||
import sys
|
||||
import os
|
||||
import table
|
||||
|
||||
sys.path.append(os.path.dirname(sys.argv[0]))
|
||||
|
||||
class Table(table.TableEngine):
|
||||
def __init__(self):
|
||||
table.TableEngine.__init__(self, True, False)
|
||||
|
||||
def doinkex(self):
|
||||
self.mergeSplit()
|
||||
|
||||
if __name__ == '__main__': #pragma: no cover
|
||||
Table().run()
|
@ -0,0 +1,18 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<inkscape-extension xmlns="http://www.inkscape.org/namespace/inkscape/extension">
|
||||
<name>Selected columns</name>
|
||||
<id>fablabchemnitz.de.table_remove_columns</id>
|
||||
<effect>
|
||||
<object-type>all</object-type>
|
||||
<effects-menu>
|
||||
<submenu name="FabLab Chemnitz">
|
||||
<submenu name="Table">
|
||||
<submenu name="Remove" />
|
||||
</submenu>
|
||||
</submenu>
|
||||
</effects-menu>
|
||||
</effect>
|
||||
<script>
|
||||
<command location="inx" interpreter="python">table_remove_columns.py</command>
|
||||
</script>
|
||||
</inkscape-extension>
|
32
extensions/fablabchemnitz/table_support/table_remove_columns.py
Executable file
32
extensions/fablabchemnitz/table_support/table_remove_columns.py
Executable file
@ -0,0 +1,32 @@
|
||||
#!/usr/bin/env python3
|
||||
"""
|
||||
table.py
|
||||
Table support for Inkscape
|
||||
|
||||
Copyright (C) 2011 Cosmin Popescu, cosminadrianpopescu@gmail.com
|
||||
|
||||
This program is free software; you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as published by
|
||||
the Free Software Foundation; either version 2 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 General Public License for more details.
|
||||
"""
|
||||
import sys
|
||||
import os
|
||||
import table
|
||||
|
||||
sys.path.append(os.path.dirname(sys.argv[0]))
|
||||
|
||||
class Table(table.TableEngine):
|
||||
def __init__(self):
|
||||
table.TableEngine.__init__(self, True, True)
|
||||
|
||||
def doinkex(self):
|
||||
self.removeRowsColumns(self.cell_type_column)
|
||||
|
||||
if __name__ == '__main__': #pragma: no cover
|
||||
Table().run()
|
@ -0,0 +1,18 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<inkscape-extension xmlns="http://www.inkscape.org/namespace/inkscape/extension">
|
||||
<name>Selected rows</name>
|
||||
<id>fablabchemnitz.de.table_remove_rows</id>
|
||||
<effect>
|
||||
<object-type>all</object-type>
|
||||
<effects-menu>
|
||||
<submenu name="FabLab Chemnitz">
|
||||
<submenu name="Table">
|
||||
<submenu name="Remove" />
|
||||
</submenu>
|
||||
</submenu>
|
||||
</effects-menu>
|
||||
</effect>
|
||||
<script>
|
||||
<command location="inx" interpreter="python">table_remove_rows.py</command>
|
||||
</script>
|
||||
</inkscape-extension>
|
32
extensions/fablabchemnitz/table_support/table_remove_rows.py
Executable file
32
extensions/fablabchemnitz/table_support/table_remove_rows.py
Executable file
@ -0,0 +1,32 @@
|
||||
#!/usr/bin/env python3
|
||||
"""
|
||||
table.py
|
||||
Table support for Inkscape
|
||||
|
||||
Copyright (C) 2011 Cosmin Popescu, cosminadrianpopescu@gmail.com
|
||||
|
||||
This program is free software; you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as published by
|
||||
the Free Software Foundation; either version 2 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 General Public License for more details.
|
||||
"""
|
||||
import sys
|
||||
import os
|
||||
import table
|
||||
|
||||
sys.path.append(os.path.dirname(sys.argv[0]))
|
||||
|
||||
class Table(table.TableEngine):
|
||||
def __init__(self):
|
||||
table.TableEngine.__init__(self, True, True)
|
||||
|
||||
def doinkex(self):
|
||||
self.removeRowsColumns(self.cell_type_row)
|
||||
|
||||
if __name__ == '__main__': #pragma: no cover
|
||||
Table().run()
|
Loading…
Reference in New Issue
Block a user