diff options
| -rw-r--r-- | share/extensions/docinfo.inx | 21 | ||||
| -rw-r--r-- | share/extensions/dpi90to96.inx | 23 | ||||
| -rw-r--r-- | share/extensions/dpi96to90.inx | 23 | ||||
| -rw-r--r-- | share/extensions/dpiswitcher.py | 219 | ||||
| -rw-r--r-- | src/file.cpp | 72 |
5 files changed, 339 insertions, 19 deletions
diff --git a/share/extensions/docinfo.inx b/share/extensions/docinfo.inx new file mode 100644 index 000000000..c3d76a960 --- /dev/null +++ b/share/extensions/docinfo.inx @@ -0,0 +1,21 @@ +<?xml version="1.0" encoding="UTF-8"?> +<inkscape-extension xmlns="http://www.inkscape.org/namespace/inkscape/extension"> + <_name>DOC Info</_name> + <id>org.inkscape.docinfo</id> + <dependency type="executable" location="extensions">dpiswitcher.py</dependency> + <dependency type="executable" location="extensions">inkex.py</dependency> + <param name="action" type="notebook" gui-hidden="true"> + <page name="page_info" _gui-text="Show page info"> + <_param name="d" type="description">Choose this tab if you would like to see page info previously to apply DPI Switcher.</_param> + </page> + </param> + <effect needs-live-preview="false"> + <object-type>all</object-type> + <effects-menu> + <submenu _name="Document"/> + </effects-menu> + </effect> + <script> + <command reldir="extensions" interpreter="python">dpiswitcher.py</command> + </script> +</inkscape-extension> diff --git a/share/extensions/dpi90to96.inx b/share/extensions/dpi90to96.inx new file mode 100644 index 000000000..e7ad4a895 --- /dev/null +++ b/share/extensions/dpi90to96.inx @@ -0,0 +1,23 @@ +<?xml version="1.0" encoding="UTF-8"?> +<inkscape-extension xmlns="http://www.inkscape.org/namespace/inkscape/extension"> + <_name>DPI 90 to 96</_name> + <id>org.inkscape.dpi90to96</id> + <dependency type="executable" location="extensions">dpiswitcher.py</dependency> + <dependency type="executable" location="extensions">inkex.py</dependency> + <param name="action" type="notebook" gui-hidden="true"> + <page name="dpi_swicher" > + <param name="switcher" type="enum" gui-hidden="true"> + <item value="0">DPI Switch from 90 to 96</item> + </param> + </page> + </param> + <effect needs-live-preview="false"> + <object-type>all</object-type> + <effects-menu> + <submenu _name="Document"/> + </effects-menu> + </effect> + <script> + <command reldir="extensions" interpreter="python">dpiswitcher.py</command> + </script> +</inkscape-extension> diff --git a/share/extensions/dpi96to90.inx b/share/extensions/dpi96to90.inx new file mode 100644 index 000000000..11d1cb40b --- /dev/null +++ b/share/extensions/dpi96to90.inx @@ -0,0 +1,23 @@ +<?xml version="1.0" encoding="UTF-8"?> +<inkscape-extension xmlns="http://www.inkscape.org/namespace/inkscape/extension"> + <_name>DPI 96 to 90</_name> + <id>org.inkscape.dpi96to90</id> + <dependency type="executable" location="extensions">dpiswitcher.py</dependency> + <dependency type="executable" location="extensions">inkex.py</dependency> + <param name="action" type="notebook" gui-hidden="true"> + <page name="dpi_swicher" > + <param name="switcher" type="enum" gui-hidden="true"> + <item value="1">DPI Switch from 96 to 90</item> + </param> + </page> + </param> + <effect needs-live-preview="false"> + <object-type>all</object-type> + <effects-menu> + <submenu _name="Document"/> + </effects-menu> + </effect> + <script> + <command reldir="extensions" interpreter="python">dpiswitcher.py</command> + </script> +</inkscape-extension> diff --git a/share/extensions/dpiswitcher.py b/share/extensions/dpiswitcher.py new file mode 100644 index 000000000..e7adbc0cf --- /dev/null +++ b/share/extensions/dpiswitcher.py @@ -0,0 +1,219 @@ +#!/usr/bin/env python +''' +This extension scale or reduce a document to fit diferent SVG DPI -90/96- + +Copyright (C) 2012 Jabiertxo Arraiza, jabier.arraiza@marker.es + +Version 0.5 - DPI Switcher + +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, sys, re, string +from lxml import etree + +class DPISwitcher(inkex.Effect): + + def __init__(self): + inkex.Effect.__init__(self) + self.OptionParser.add_option("--switcher", action="store", + type="string", dest="switcher", default="0", + help="Select the DPI switch you want") + self.OptionParser.add_option("--action", action="store", + type="string", dest="action", + default=None, help="") + self.factor_a = 90.0/96.0 + self.factor_b = 96.0/90.0 + self.units = "px" + self.unitExponent = 1.0 + + def scaleRoot(self, svg): + widthNumber = re.sub("[a-zA-Z]", "", svg.get('width')) + heightNumber = re.sub("[a-zA-Z]", "", svg.get('height')) + widthDoc = str(float(widthNumber) * self.factor_a * self.unitExponent) + heightDoc = str(float(heightNumber) * self.factor_a * self.unitExponent) + if svg.get('viewBox'): + widthNumber = svg.get('viewBox').split(" ")[2] + heightNumber = svg.get('viewBox').split(" ")[3] + if svg.get('height'): + svg.set('height', heightDoc) + if svg.get('width'): + svg.set('width', widthDoc) + if svg.get('viewBox'): + svg.set('viewBox',"0 0 " + str(float(widthNumber) * self.factor_a) + " " + str(float(heightNumber) * self.factor_a)) + if self.options.switcher == "1": + self.scaleGuides(svg) + self.scaleGrid(svg) + for element in svg: + box3DSide = element.get(inkex.addNS('box3dsidetype', 'inkscape')) + if box3DSide: + continue + uri, tag = element.tag.split("}") + width_scale = self.factor_a + height_scale = self.factor_a + if tag == "rect" or tag == "image" or tag == "path" or tag == "circle" or tag == "ellipse" or tag == "text": + if element.get('width') is not None and \ + (re.sub("[0-9]*\.?[0-9]", "", element.get('width')) == "%" or \ + re.sub("[0-9]*\.?[0-9]", "", element.get('width')) == "px"): + width_scale = 1.0; + if element.get('height') is not None and \ + (re.sub("[0-9]*\.?[0-9]", "", element.get('height')) == "%" or \ + re.sub("[0-9]*\.?[0-9]", "", element.get('height')) == "px"): + height_scale = 1.0; + if element.get('x') is not None and \ + re.sub("[0-9]*\.?[0-9]", "", element.get('x')) == "%": + xpos = str(float(element.get('x').replace('%','')) * self.factor_b) + '%' + element.set('x', xpos) + if element.get('y') is not None and \ + re.sub("[0-9]*\.?[0-9]", "", element.get('y')) == "%": + ypos = str(float(element.get('y').replace('%','')) * self.factor_b) + '%' + element.set('y', ypos) + if element.get('transform'): + if "matrix" in str(element.get('transform')) and width_scale != 1.0: + result = re.sub(r".*?matrix( \(|\()(.*?)\)", self.matrixElement, str(element.get('transform'))) + element.set('transform', result) + if "scale" in str(element.get('transform')) and width_scale != 1.0: + result = re.sub(r".*?scale( \(|\()(.*?)\)", self.scaleElement, str(element.get('transform'))) + element.set('transform', result) + if "translate" in str(element.get('transform')) and width_scale != 1.0: + result = re.sub(r".*?translate( \(|\()(.*?)\)", self.translateElement, str(element.get('transform'))) + element.set('transform', result) + if "skew" in str(element.get('transform')) and width_scale != 1.0: + result = re.sub(r".*?skew( \(|\()(.*?)\)", self.skewElement, str(element.get('transform'))) + element.set('transform', result) + if "scale" not in str(element.get('transform')) and "matrix" not in str(element.get('transform')): + element.set('transform', str(element.get('transform')) + "scale(" + str( width_scale) + ", " + str(height_scale) + ")") + else: + element.set('transform', "scale(" + str(width_scale) + ", " + str(height_scale) + ")") + + #a dictionary of unit to user unit conversion factors + __uuconv = {'in':96.0, 'pt':1.33333333333, 'px':1.0, 'mm':3.77952755913, 'cm':37.7952755913, + 'm':3779.52755913, 'km':3779527.55913, 'pc':16.0, 'yd':3456.0 , 'ft':1152.0} + + __uuconvLegazy = {'in':90.0, 'pt':1.25, 'px':1, 'mm':3.5433070866, 'cm':35.433070866, 'm':3543.3070866, + 'km':3543307.0866, 'pc':15.0, 'yd':3240 , 'ft':1080} + + def scaleElement(self, m): + scaleVal = m.group(2).replace(" ","") + total = scaleVal.count(',') + if total == 1: + scaleVal = scaleVal.split(",") + return "matrix(" + str(float(scaleVal[0]) * self.factor_a) + ",0,0," + str(float(scaleVal[1]) * self.factor_a) + ",0,0)" + else: + return "matrix(" + str(float(scaleVal) * self.factor_a) + ",0,0," + str(float(scaleVal) * self.factor_a) + ",0,0)" + + + def translateElement(self, m): + translateVal = m.group(2).replace(" ","") + total = translateVal.count(',') + if total == 1: + translateVal = translateVal.split(",") + return "matrix(" + str(self.factor_a) + ",0,0," + str(self.factor_a) + "," + str(float(translateVal[0]) * self.factor_a) + "," + str(float(translateVal[1]) * self.factor_a) + ")" + else: + return "matrix(" + str(self.factor_a) + ",0,0," + str(self.factor_a) + "," + str(float(translateVal) * self.factor_a) + "," + str(float(translateVal) * self.factor_a) + ")" + + def skewElement(self, m): + skeweVal = m.group(2).replace(" ","") + total = skewVal.count(',') + if total == 1: + skeweVal = skewVal.split(",") + return "skew(" + str(float(skewVal[0]) * self.factor_a) + "," + str(float(skewVal[1]) * self.factor_a) + ") matrix(" + str(self.factor_a) + ",0,0," + str(self.factor_a) + ",0,0)" + else: + return "skew(" + str(float(skewVal) * self.factor_a) + ") matrix(" + str(self.factor_a) + ",0,0," + str(self.factor_a) + ",0,0)" + + def matrixElement(self, m): + matrixVal = m.group(2).replace(" ","") + total = matrixVal.count(',') + matrixVal = matrixVal.split(",") + if total == 5: + return "matrix(" + str(float(matrixVal[0]) * self.factor_a) + "," + matrixVal[1] + "," + matrixVal[2] + "," + str(float(matrixVal[3]) * self.factor_a) + "," + str(float(matrixVal[4]) * self.factor_a) + "," + str(float(matrixVal[5]) * self.factor_a) + ")" + + def scaleGuides(self, svg): + xpathStr = '//sodipodi:guide' + guides = svg.xpath(xpathStr, namespaces=inkex.NSS) + for guide in guides: + point = string.split(guide.get("position"), ",") + guide.set("position", str(float(point[0].strip()) * self.factor_a ) + "," + str(float(point[1].strip()) * self.factor_a )) + + def scaleGrid(self, svg): + xpathStr = '//inkscape:grid' + grids = svg.xpath(xpathStr, namespaces=inkex.NSS) + for grid in grids: + grid.set("units", "px") + if grid.get("spacingx"): + spacingx = str(float(re.sub("[a-zA-Z]", "", grid.get("spacingx"))) * self.factor_a) + "px" + grid.set("spacingx", str(spacingx)) + if grid.get("spacingy"): + spacingy = str(float(re.sub("[a-zA-Z]", "", grid.get("spacingy"))) * self.factor_a) + "px" + grid.set("spacingy", str(spacingy)) + if grid.get("originx"): + originx = str(float(re.sub("[a-zA-Z]", "", grid.get("originx"))) * self.factor_a) + "px" + grid.set("originx", str(originx)) + if grid.get("originy"): + originy = str(float(re.sub("[a-zA-Z]", "", grid.get("originy"))) * self.factor_a) + "px" + grid.set("originy", str(originy)) + + def effect(self): + action = self.options.action.strip("\"") # TODO Is this a bug? (Extra " characters) + saveout = sys.stdout + sys.stdout = sys.stderr + svg = self.document.getroot() + if action == "page_info": + print ":::SVG document related info:::" + print "version: " + str(svg.get(inkex.addNS('version',u'inkscape'))) + width = svg.get('width') + if width: + print "width: " + width + height = svg.get('height') + if height: + print "height: " + height + viewBox = svg.get('viewBox') + if viewBox: + print "viewBox: " + viewBox + namedview = svg.find(inkex.addNS('namedview', 'sodipodi')) + docunits= namedview.get(inkex.addNS('document-units', 'inkscape')) + if docunits: + print "document-units: " + docunits + units = namedview.get('units') + if units: + print "units: " + units + xpathStr = '//sodipodi:guide' + guides = svg.xpath(xpathStr, namespaces=inkex.NSS) + xpathStr = '//inkscape:grid' + if guides: + numberGuides = len(guides) + print "Document has " + str(numberGuides) + " guides" + grids = svg.xpath(xpathStr, namespaces=inkex.NSS) + i = 1 + for grid in grids: + print "Grid number " + str(i) + ": Units: " + grid.get("units") + i = i+1 + else: + if self.options.switcher == "0": + self.factor_a = 96.0/90.0 + self.factor_b = 90.0/96.0 + namedview = svg.find(inkex.addNS('namedview', 'sodipodi')) + namedview.set(inkex.addNS('document-units', 'inkscape'), "px") + self.units = re.sub("[0-9]*\.?[0-9]", "", svg.get('width')) + if self.units and self.units <> "px" and self.units <> "" and self.units <> "%": + if self.options.switcher == "0": + self.unitExponent = 1.0/(self.factor_a/self.__uuconv[self.units]) + else: + self.unitExponent = 1.0/(self.factor_a/self.__uuconvLegazy[self.units]) + self.scaleRoot(svg); + sys.stdout = saveout + +effect = DPISwitcher() +effect.affect() diff --git a/src/file.cpp b/src/file.cpp index ee66cc162..38c07311d 100644 --- a/src/file.cpp +++ b/src/file.cpp @@ -34,6 +34,7 @@ #include "ui/dialog/ocaldialogs.h" #include "desktop.h" +#include "extension/effect.h" #include "document-private.h" #include "document-undo.h" #include "ui/tools/tool-base.h" @@ -312,14 +313,13 @@ bool sp_file_open(const Glib::ustring &uri, // std::cout << " SVG file from old Inkscape version detected: " // << sp_version_to_string(root->version.inkscape) << std::endl; - - static const double ratio = 90.0/96.0; bool need_fix_viewbox = false; bool need_fix_units = false; bool need_fix_guides = false; bool need_fix_grid_mm = false; + bool is_extension = false; // Check if potentially need viewbox or unit fix switch (root->width.unit) { @@ -358,20 +358,18 @@ bool sp_file_open(const Glib::ustring &uri, if (!root->viewBox_set && need_fix_viewbox) { std::string msg = _( - "Old Inkscape files used 1in == 90px. CSS requires 1in == 96px.\n" + "Old Inkscape files use 1in == 90px. CSS requires 1in == 96px.\n" "Drawing elements may be too small. This can be corrected by\n" - "setting the SVG 'viewBox' to compensate." ); - // "either setting the SVG 'viewBox' to compensate or by scaling\n" - // "all the elements in the drawing." + "either setting the SVG 'viewBox' to compensate or by scaling\n" + "all the elements in the drawing."); Gtk::Dialog scaleDialog( _("Old Inkscape file detected (90 DPI)"), false); Gtk::Label info; info.set_markup(msg.c_str()); info.show(); scaleDialog.get_content_area()->pack_start(info, false, false, 20); scaleDialog.add_button("Set 'viewBox'", 1); - // scaleDialog.add_button("Scale elements", 2); + scaleDialog.add_button("Scale elements", 2); scaleDialog.add_button("Ignore", 3); - gint response = scaleDialog.run(); if (response == 1) { doc->setViewBox(Geom::Rect::from_xywh( @@ -379,27 +377,42 @@ bool sp_file_open(const Glib::ustring &uri, doc->getWidth().value("px") * ratio, doc->getHeight().value("px") * ratio)); } else if (response == 2 ) { - // Insert DPISwitcher code + std::list<Inkscape::Extension::Effect *> effects; + Inkscape::Extension::db.get_effect_list(effects); + std::list<Inkscape::Extension::Effect *>::iterator it = effects.begin(); + bool did = false; + while (it != effects.end()) { + if (strcmp((*it)->get_id(), "org.inkscape.dpi90to96") == 0) { + Inkscape::UI::View::View *view = desktop; + (*it)->effect(view); + did = true; + break; + } + ++it; + } + if (!did) { + std::cerr << "sp_file_open: Failed to find dpi90to96 extension." << std::endl; + } + is_extension = true; } need_fix_guides = true; // Always fix guides } if (need_fix_units) { std::string msg = ( - "Old Inkscape files used 1in == 90px. CSS requires 1in == 96px.\n" + "Old Inkscape files use 1in == 90px. CSS requires 1in == 96px.\n" "Drawings meant to match a physical size (e.g. Letter or A4)\n" - "will be too small. Scaling the drawing can correct for this.\n" ); - // "Internal scaling can be handled either by setting the SVG 'viewBox'\n" - // "attribute to compensate or by scaling all objects in the drawing." + "will be too small. Scaling the drawing can correct for this.\n" + "Internal scaling can be handled either by setting the SVG 'viewBox'\n" + "attribute to compensate or by scaling all objects in the drawing."); Gtk::Dialog scaleDialog( _("Old Inkscape file detected (90 DPI)"), false); Gtk::Label info; info.set_markup(msg.c_str()); info.show(); scaleDialog.get_content_area()->pack_start(info, false, false, 20); - scaleDialog.add_button("Scale drawing", 1); - // scaleDialog.add_button("Set 'viewBox'", 1); - // scaleDialog.add_button("Scale elements", 2); - scaleDialog.add_button("Ignore", 3); + scaleDialog.add_button("Set 'viewBox'", 1); + scaleDialog.add_button("Scale elements", 2); + scaleDialog.add_button("Ignore", 3); gint response = scaleDialog.run(); if (response == 1) { @@ -418,7 +431,24 @@ bool sp_file_open(const Glib::ustring &uri, need_fix_guides = true; // Only fix guides if drawing scaled } else if (response == 2) { - // Insert DPISwitcher code + std::list<Inkscape::Extension::Effect *> effects; + Inkscape::Extension::db.get_effect_list(effects); + std::list<Inkscape::Extension::Effect *>::iterator it = effects.begin(); + bool did = false; + while (it != effects.end()){ + if (strcmp((*it)->get_id(), "org.inkscape.dpi90to96") == 0) { + Inkscape::UI::View::View *view = desktop; + (*it)->effect(view); + did = true; + break; + } + ++it; + } + if (!did) { + std::cerr << "sp_file_open: Failed to find dpi90to96 extension." << std::endl; + } + need_fix_guides = true; // Only fix guides if drawing scaled + is_extension = true; } else { // Ignore need_fix_grid_mm = true; @@ -467,7 +497,11 @@ bool sp_file_open(const Glib::ustring &uri, // HACK: Scaling the document does not seem to cause // grids defined in document units to be updated. // This forces an update. - xy->Scale( Geom::Scale(1,1) ); + if(is_extension){ + xy->Scale( Geom::Scale(ratio,ratio).inverse() ); + } else { + xy->Scale( Geom::Scale(1,1) ); + } } } } |
