diff --git a/README.md b/README.md
index 91c2006a..7f1d09e4 100644
--- a/README.md
+++ b/README.md
@@ -1,6 +1,6 @@
# MightyScape for Inkscape 1.0+
-In short: A maintained extension collection for Inkscape 1.0+, working on Windows and Linux. There are **233 extension folders** with **406 .inx files** inside. We also take part at https://inkscape.org/gallery/=extension/ (with single extension uploads).
+In short: A maintained extension collection for Inkscape 1.0+, working on Windows and Linux. There are **234 extension folders** with **407 .inx files** inside. We also take part at https://inkscape.org/gallery/=extension/ (with single extension uploads).
# About MightyScape
diff --git a/extensions/fablabchemnitz/000_validate.sh b/extensions/fablabchemnitz/000_validate.sh
index f6353e1d..cb8e0d6e 100755
--- a/extensions/fablabchemnitz/000_validate.sh
+++ b/extensions/fablabchemnitz/000_validate.sh
@@ -1,12 +1,14 @@
#!/bin/bash
clear
+
echo "--> Validating inx files with xmllint. Only errors are printed to console"
for folder in */ ; do
xmllint --noout --relaxng ./inkscape.extension.rng ${folder}*.inx > /dev/null 2>> 000_xmllint.out
done
grep -v "validates\|warning: failed to load external entity" 000_xmllint.out; rm 000_xmllint.out
+
#complete set of meta information
AGGLOMERATED_JSON=""
for folder in */ ; do
@@ -23,35 +25,65 @@ done
#print overall json
#echo $AGGLOMERATED_JSON | jq
+
echo "--> Show unique license kinds used:"
echo $AGGLOMERATED_JSON | jq -r '.[]|{license}|.[]' | sort | uniq -c
+
echo "--> show unique list of involved contributors (thanks/credits):"
#echo $AGGLOMERATED_JSON | jq -r '.[]|{main_authors}|.[]|.[]' | sort | uniq -c
echo $AGGLOMERATED_JSON | jq -r '.[]|{main_authors}|.[]|.[]' | sort | uniq
+
#show extensions which are in gallery
GALLERY_EXTENSIONS=$(echo $AGGLOMERATED_JSON | jq -r '.[]|{inkscape_gallery_url}|.[]' | sort | grep -v "null")
for GALLERY_EXTENSION in ${GALLERY_EXTENSIONS}; do
EXTENSION=$(echo ${AGGLOMERATED_JSON} | jq -r '.[]|select(.inkscape_gallery_url=="'$GALLERY_EXTENSION'")|{name}|.[]')
done
+
echo "--> Count of inx files:"
INX=$(find ./ -type f -name "*.inx" | wc -l)
echo INX: $INX
+
echo "--> Count of extension folders:"
FOLDERS=$(ls -d */ | wc -l)
echo FOLDERS: $FOLDERS
+
README="../../README.md"
#replace values in README.md
sed -i 's/\*\*.* extension folders\*\*/\*\*'${FOLDERS}' extension folders\*\*/g' ${README}
sed -i 's/\*\* with .* \.inx files\*\*/\*\* with \*\*'${INX}' \.inx files\*\*/g' ${README}
+
echo "Removing unrequired pyc cache files"
find . -type d -name "__pycache__" -exec rm -rf {} \;
+
+read -p "Build local gallery extension zip files?" -n 1 -r
+echo
+if [[ $REPLY =~ ^[Yy]$ ]]; then
+ echo "Building extension zip files for zipmirror"
+ TARGETDIR="../../../mightyscape-1.X-zipmirror"
+ mkdir -p $TARGETDIR > /dev/null 2>&1
+
+ for EXTENSION in */; do
+ EXTENSION="${EXTENSION%/}" #strip trailing slash
+ EXTRA=""
+ if [[ $EXTENSION == "styles_to_layers" ]] || [[ $EXTENSION == "ungrouper_and_element_migrator_filter" ]] || [[ $EXTENSION == "epilog_dashboard_bbox_adjust" ]]; then
+ EXTRA="${EXTRA} apply_transformations/"
+ elif [[ $EXTENSION == "styles_to_layers" ]] || [[ $EXTENSION == "ungrouper_and_element_migrator_filter" ]]; then
+ EXTRA="${EXTRA} remove_empty_groups/"
+ fi
+ ZIPFILE=$TARGETDIR/$EXTENSION.zip
+ zip -ru $ZIPFILE $EXTENSION/ 000_about_fablabchemnitz.svg $EXTRA > /dev/null 2>&1
+ echo "--> creating/updating $ZIPFILE"
+ done
+fi
+
+
read -p "Build local gallery extension zip files?" -n 1 -r
echo
if [[ $REPLY =~ ^[Yy]$ ]]; then
@@ -64,7 +96,7 @@ if [[ $REPLY =~ ^[Yy]$ ]]; then
for GALLERY_EXTENSION in ${GALLERY_EXTENSIONS}; do
EXTENSION="$(echo ${AGGLOMERATED_JSON} | jq -r '.[]|select(.inkscape_gallery_url=="'$GALLERY_EXTENSION'")|{path}|.[]')"
EXTRA=""
- if [[ $EXTENSION == "styles_to_layers" ]] || [[ $EXTENSION == "ungrouper_and_element_migrator_filter" ]]; then
+ if [[ $EXTENSION == "styles_to_layers" ]] || [[ $EXTENSION == "ungrouper_and_element_migrator_filter" ]] || [[ $EXTENSION == "epilog_dashboard_bbox_adjust" ]]; then
EXTRA="${EXTRA} apply_transformations/"
elif [[ $EXTENSION == "styles_to_layers" ]] || [[ $EXTENSION == "ungrouper_and_element_migrator_filter" ]]; then
EXTRA="${EXTRA} remove_empty_groups/"
@@ -72,6 +104,6 @@ if [[ $REPLY =~ ^[Yy]$ ]]; then
ZIPFILE=$TARGETDIR/$EXTENSION.zip
rm $ZIPFILE > /dev/null 2>&1
echo "--> creating $ZIPFILE"
- zip -r $ZIPFILE $EXTENSION/ 000_about_fablabchemnitz.svg $EXTRA
+ zip -ru $ZIPFILE $EXTENSION/ 000_about_fablabchemnitz.svg $EXTRA
done
fi
diff --git a/extensions/fablabchemnitz/epilog_dashboard_bbox_adjust/epilog_dashboard_bbox_adjust.inx b/extensions/fablabchemnitz/epilog_dashboard_bbox_adjust/epilog_dashboard_bbox_adjust.inx
index bb13a277..0e0a14d8 100644
--- a/extensions/fablabchemnitz/epilog_dashboard_bbox_adjust/epilog_dashboard_bbox_adjust.inx
+++ b/extensions/fablabchemnitz/epilog_dashboard_bbox_adjust/epilog_dashboard_bbox_adjust.inx
@@ -4,8 +4,9 @@
fablabchemnitz.de.epilog_dashboard_bbox_adjust
+ false
1.0
-
+
@@ -19,6 +20,7 @@
false
+ false
diff --git a/extensions/fablabchemnitz/epilog_dashboard_bbox_adjust/epilog_dashboard_bbox_adjust.py b/extensions/fablabchemnitz/epilog_dashboard_bbox_adjust/epilog_dashboard_bbox_adjust.py
index 0f70f858..4b44e3cd 100644
--- a/extensions/fablabchemnitz/epilog_dashboard_bbox_adjust/epilog_dashboard_bbox_adjust.py
+++ b/extensions/fablabchemnitz/epilog_dashboard_bbox_adjust/epilog_dashboard_bbox_adjust.py
@@ -10,7 +10,7 @@ So we add a default (small) amount of 1.0 doc units to expand the document's can
Author: Mario Voigt / FabLab Chemnitz
Mail: mario.voigt@stadtfabrikanten.org
Date: 21.04.2021
-Last patch: 27.05.2021
+Last patch: 26.0510.2021
License: GNU GPL v3
#known bugs:
@@ -23,8 +23,10 @@ License: GNU GPL v3
'''
import math
+import sys
import inkex
from inkex import Transform
+sys.path.append("../apply_transformations")
class EpilogDashboardBboxAdjust(inkex.EffectExtension):
@@ -39,33 +41,105 @@ class EpilogDashboardBboxAdjust(inkex.EffectExtension):
def add_arguments(self, pars):
pars.add_argument("--tab")
+ pars.add_argument("--apply_transformations", type=inkex.Boolean, default=False, help="Run 'Apply Transformations' extension before running vpype. Helps avoiding geometry shifting")
pars.add_argument("--offset", type=float, default="1.0", help="XY Offset (mm) from top left corner")
pars.add_argument("--removal", default="none", help="Remove all elements outside the bounding box or selection")
pars.add_argument("--use_machine_size", type=inkex.Boolean, default=False, help="Use machine size")
pars.add_argument("--machine_size", default="812x508", help="Machine/Size")
pars.add_argument("--debug", type=inkex.Boolean, default=False, help="Debug output")
-
+ pars.add_argument("--skip_errors", type=inkex.Boolean, default=False, help="Skip on errors")
+
def effect(self):
+
+ applyTransformationsAvailable = False # at first we apply external extension
+ try:
+ import apply_transformations
+ applyTransformationsAvailable = True
+ except Exception as e:
+ # self.msg(e)
+ self.msg("Calling 'Apply Transformations' extension failed. Maybe the extension is not installed. You can download it from official InkScape Gallery. Skipping ...")
+
+ if self.options.apply_transformations is True and applyTransformationsAvailable is True:
+ apply_transformations.ApplyTransformations().recursiveFuseTransform(self.document.getroot())
+
offset = self.options.offset
- #units = self.svg.unit
units = "mm" #force millimeters
+ scale_factor = self.svg.unittouu("1px")
+ #namedView = self.document.getroot().find(inkex.addNS('namedview', 'sodipodi'))
+ #doc_units = namedView.get(inkex.addNS('document-units', 'inkscape'))
+ #doc_units = self.svg.unit
+ #https://wiki.inkscape.org/wiki/Units_In_Inkscape
+ #remove sodipodi units. Some actions add units to namedview, but we already have "inkscape:document-units".
+ #namedView.pop('units')
+ #del namedView.attrib["units"] #does the same like namedView.pop('units')
# create a new bounding box and get the bbox size of all elements of the document (we cannot use the page's bbox)
bbox = inkex.BoundingBox()
if len(self.svg.selected) > 0:
- bbox = self.svg.selection.bounding_box()
- #for element in self.svg.selected.values():
- # bbox += element.bounding_box()
+ #bbox = self.svg.selection.bounding_box() #it could be so easy! But ...
+ for element in self.svg.selected.values():
+ '''
+ ...rectangles cause some strangle scaling issue, offendingly caused by namedview units.
+ The rectangle attributes are set in px. They ignore the real units from namedview.
+ Strange fact: ellipses, spirals and other primitives work flawlessly.
+ '''
+ if isinstance (element, inkex.Rectangle):
+ bbox += element.bounding_box() * scale_factor
+ elif isinstance (element, inkex.TextElement):
+ if self.options.skip_errors is False:
+ self.msg("Text elements are not supported!")
+ return
+ else:
+ continue
+ else:
+ bbox += element.bounding_box()
else:
#for element in self.svg.root.getchildren():
for element in self.document.getroot().iter("*"):
if isinstance (element, inkex.ShapeElement) and element.tag != inkex.addNS('use','svg') and element.get('inkscape:groupmode') != 'layer': #bbox fails for svg:use elements and layers:
- bbox += element.bounding_box()
+ if isinstance (element, inkex.Rectangle):
+ bbox += element.bounding_box() * scale_factor
+ elif isinstance (element, inkex.TextElement):
+ if self.options.skip_errors is False:
+ self.msg("Text elements are not supported!")
+ return
+ else:
+ continue
+ else:
+ bbox += element.bounding_box()
if abs(bbox.width) == math.inf or abs(bbox.height) == math.inf:
- inkex.utils.debug("Error calculating bounding box! Impossible to continue!")
+ inkex.utils.debug("Error while calculating overall bounding box! Check your element types. Things like svg:text or svg:use are not supported. Impossible to continue!")
return
+ #if len(self.svg.selected) > 0:
+ # selected = self.svg.selected
+ #else:
+ # selected = self.svg.root.getchildren()
+ #for element in selected:
+ # transform = inkex.Transform()
+ # parent = element.getparent()
+ # if parent is not None and isinstance(parent, inkex.ShapeElement):
+ # transform = parent.composed_transform()
+ # try:
+ # '''
+ # ...rectangles cause some strangle scaling issue, offendingly caused by namedview units.
+ # The rectangle attributes are set in px. They ignore the real units from namedview.
+ # Strange fact: ellipses, spirals and other primitives work flawlessly.
+ # '''
+ # if isinstance (element, inkex.Rectangle) or isinstance (element, inkex.TextElement):
+ # bbox += element.bounding_box(transform) * scale_factor
+ # else:
+ # bbox += element.bounding_box(transform)
+ # except Exception:
+ # logger.exception("Bounding box not computed")
+ # logger.info("Skipping bounding box")
+ # transform = element.composed_transform()
+ # x1, y1 = transform.apply_to_point([0, 0])
+ # x2, y2 = transform.apply_to_point([1, 1])
+ # bbox += inkex.BoundingBox((x1, x2), (y1, y2))
+
+
# adjust the viewBox to the bbox size and add the desired offset
if self.options.use_machine_size is True:
machineWidth = float(self.options.machine_size.split('x')[0])
diff --git a/extensions/fablabchemnitz/export_selection_as/export_selection_as.inx b/extensions/fablabchemnitz/export_selection_as/export_selection_as.inx
index be0f65e2..29c517f9 100644
--- a/extensions/fablabchemnitz/export_selection_as/export_selection_as.inx
+++ b/extensions/fablabchemnitz/export_selection_as/export_selection_as.inx
@@ -6,6 +6,14 @@
false
1.000
+
+
+
+
+
+
+
+
./inkscape_export/
false
/usr/share/inkscape/extensions/dxf_outlines.py
@@ -16,6 +24,7 @@
96
false
false
+ false
diff --git a/extensions/fablabchemnitz/export_selection_as/export_selection_as.py b/extensions/fablabchemnitz/export_selection_as/export_selection_as.py
index 92cb76bc..d95947f8 100644
--- a/extensions/fablabchemnitz/export_selection_as/export_selection_as.py
+++ b/extensions/fablabchemnitz/export_selection_as/export_selection_as.py
@@ -32,6 +32,7 @@ class ExportObject(inkex.EffectExtension):
pars.add_argument("--tab")
pars.add_argument("--wrap_transform", type=inkex.Boolean, default=False, help="Wrap final document in transform")
pars.add_argument("--border_offset", type=float, default=1.000, help="Add border offset around selection")
+ pars.add_argument("--border_offset_unit", default="mm", help="Offset unit")
pars.add_argument("--export_dir", default="~/inkscape_export/", help="Location to save exported documents")
pars.add_argument("--opendir", type=inkex.Boolean, default=False, help="Open containing output directory after export")
pars.add_argument("--dxf_exporter_path", default="/usr/share/inkscape/extensions/dxf_outlines.py", help="Location of dxf_outlines.py")
@@ -42,6 +43,7 @@ class ExportObject(inkex.EffectExtension):
pars.add_argument("--png_dpi", type=float, default=96, help="PNG DPI (applies for export and replace)")
pars.add_argument("--replace_by_png", type=inkex.Boolean, default=False, help="Replace selection by png export")
pars.add_argument("--newwindow", type=inkex.Boolean, default=False, help="Open file in new Inkscape window")
+ pars.add_argument("--skip_errors", type=inkex.Boolean, default=False, help="Skip on errors")
def openExplorer(self, dir):
if os.name == 'nt':
@@ -61,6 +63,7 @@ class ExportObject(inkex.EffectExtension):
warnings.simplefilter("default", ResourceWarning)
def effect(self):
+ scale_factor = self.svg.unittouu("1px")
svg_export = self.options.export_svg
extra_param = "--batch-process"
@@ -90,7 +93,7 @@ class ExportObject(inkex.EffectExtension):
export_dir = Path(self.absolute_href(self.options.export_dir))
os.makedirs(export_dir, exist_ok=True)
- offset = self.options.border_offset
+ offset = self.svg.unittouu(str(self.options.border_offset) + self.options.border_offset_unit)
bbox = inkex.BoundingBox()
@@ -98,21 +101,35 @@ class ExportObject(inkex.EffectExtension):
firstId = selected[0].get('id')
parent = self.svg.getElementById(firstId).getparent()
- for elem in selected.values():
+ for element in selected.values():
transform = inkex.Transform()
- parent = elem.getparent()
+ parent = element.getparent()
if parent is not None and isinstance(parent, inkex.ShapeElement):
transform = parent.composed_transform()
try:
- bbox += elem.bounding_box(transform)
+ '''
+ ...rectangles cause some strangle scaling issue, offendingly caused by namedview units.
+ The rectangle attributes are set in px. They ignore the real units from namedview.
+ Strange fact: ellipses, spirals and other primitives work flawlessly.
+ '''
+ if isinstance (element, inkex.Rectangle):
+ bbox += element.bounding_box(transform) * scale_factor
+ elif isinstance (element, inkex.TextElement):
+ if self.options.skip_errors is False:
+ self.msg("Text elements are not supported!")
+ return
+ else:
+ continue
+ else:
+ bbox += element.bounding_box(transform)
except Exception:
logger.exception("Bounding box not computed")
logger.info("Skipping bounding box")
- transform = elem.composed_transform()
+ transform = element.composed_transform()
x1, y1 = transform.apply_to_point([0, 0])
x2, y2 = transform.apply_to_point([1, 1])
bbox += inkex.BoundingBox((x1, x2), (y1, y2))
-
+
template = self.create_document()
svg_filename = None
@@ -120,12 +137,12 @@ class ExportObject(inkex.EffectExtension):
group.attrib['id'] = GROUP_ID
group.attrib['transform'] = str(inkex.Transform(((1, 0, -bbox.left), (0, 1, -bbox.top))))
- for elem in self.svg.selected.values():
- if elem.tag == inkex.addNS('image', 'svg'):
+ for element in self.svg.selected.values():
+ if element.tag == inkex.addNS('image', 'svg'):
continue #skip images
- elem_copy = deepcopy(elem)
- elem_copy.attrib['transform'] = str(elem.composed_transform())
- elem_copy.attrib['style'] = str(elem.composed_style())
+ elem_copy = deepcopy(element)
+ elem_copy.attrib['transform'] = str(element.composed_transform())
+ elem_copy.attrib['style'] = str(element.composed_style())
group.append(elem_copy)
template.attrib['viewBox'] = f'{-offset} {-offset} {bbox.width + offset * 2} {bbox.height + offset * 2}'
@@ -133,7 +150,7 @@ class ExportObject(inkex.EffectExtension):
template.attrib['height'] = f'{bbox.height + offset * 2}' + self.svg.unit
if svg_filename is None:
- filename_base = elem.attrib.get('id', None).replace(os.sep, '_')
+ filename_base = element.attrib.get('id', None).replace(os.sep, '_')
if filename_base:
svg_filename = filename_base + '.svg'
if not filename_base: #should never be the case. Inkscape might crash if the id attribute is empty or not existent due to invalid SVG
@@ -241,8 +258,8 @@ class ExportObject(inkex.EffectExtension):
self.msg(cli_output)
#then remove the selection and replace it by png
#self.msg(parent.get('id'))
- for elem in selected.values():
- elem.delete()
+ for element in selected.values():
+ element.delete()
#read png file and get base64 string from it
try:
img = Image.open(png_export)