diff options
| author | Alvin Penner <penner@vaxxine.com> | 2012-07-28 22:31:38 +0000 |
|---|---|---|
| committer | apenner <penner@vaxxine.com> | 2012-07-28 22:31:38 +0000 |
| commit | 05837a7f5e775373c70bac26fb19374da570108b (patch) | |
| tree | 6b6797dffb572f8f5c4ca4160ac8faf21d5eea42 /share | |
| parent | do not allow sodipodi:docname to have a temporary filename (partial fix for B... (diff) | |
| download | inkscape-05837a7f5e775373c70bac26fb19374da570108b.tar.gz inkscape-05837a7f5e775373c70bac26fb19374da570108b.zip | |
add Extensions->Export->Win32 Vector Print (Bug 966244)
Fixed bugs:
- https://launchpad.net/bugs/966244
(bzr r11575)
Diffstat (limited to 'share')
| -rw-r--r-- | share/extensions/print_win32_vector.inx | 17 | ||||
| -rw-r--r-- | share/extensions/print_win32_vector.py | 208 |
2 files changed, 225 insertions, 0 deletions
diff --git a/share/extensions/print_win32_vector.inx b/share/extensions/print_win32_vector.inx new file mode 100644 index 000000000..ab66a4b77 --- /dev/null +++ b/share/extensions/print_win32_vector.inx @@ -0,0 +1,17 @@ +<?xml version="1.0" encoding="UTF-8"?> +<inkscape-extension xmlns="http://www.inkscape.org/namespace/inkscape/extension"> + <_name>Win32 Vector Print</_name> + <id>com.vaxxine.print.win32</id> + <dependency type="extension">org.inkscape.output.svg.inkscape</dependency> + <dependency type="executable" location="extensions">print_win32_vector.py</dependency> + <dependency type="executable" location="extensions">inkex.py</dependency> + <effect needs-live-preview="false"> + <object-type>all</object-type> + <effects-menu> + <submenu _name="Export"/> + </effects-menu> + </effect> + <script> + <command reldir="extensions" interpreter="python">print_win32_vector.py</command> + </script> +</inkscape-extension> diff --git a/share/extensions/print_win32_vector.py b/share/extensions/print_win32_vector.py new file mode 100644 index 000000000..49baec136 --- /dev/null +++ b/share/extensions/print_win32_vector.py @@ -0,0 +1,208 @@ +#!/usr/bin/env python +''' +print_win32_vector.py +This extension will generate vector graphics printout, specifically for Windows GDI32. + +Copyright (C) 2012 Alvin Penner, penner@vaxxine.com + +This is a modified version of the file dxf_outlines.py by Aaron Spike, aaron@ekips.org +It will write only to the default printer. +The printing preferences dialog will be called. +In order to ensure a pure vector output, use a linewidth < 1 printer pixel + +- see http://www.lessanvaezi.com/changing-printer-settings-using-the-windows-api/ +- get GdiPrintSample.zip at http://archive.msdn.microsoft.com/WindowsPrintSample + +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 ctypes import * +import inkex, simplestyle, simpletransform, cubicsuperpath +import gettext +_ = gettext.gettext + +if not inkex.sys.platform.startswith('win'): + exit(_("sorry, this will run only on Windows, exiting...")) + +myspool = WinDLL("winspool.drv") +mygdi = WinDLL("gdi32.dll") +LOGBRUSH = c_long*3 +DM_IN_PROMPT = 4 # call printer property sheet +DM_OUT_BUFFER = 2 # write to DEVMODE structure + +class MyEffect(inkex.Effect): + def __init__(self): + inkex.Effect.__init__(self) + self.visibleLayers = True # print only visible layers + + def process_shape(self, node, mat): + rgb = (0,0,0) # stroke color + fillcolor = None # fill color + stroke = 1 # pen width in printer pixels + # Very NB : If the pen width is greater than 1 then the output will Not be a vector output ! + style = node.get('style') + if style: + style = simplestyle.parseStyle(style) + if style.has_key('stroke'): + if style['stroke'] and style['stroke'] != 'none' and style['stroke'][0:3] != 'url': + rgb = simplestyle.parseColor(style['stroke']) + if style.has_key('stroke-width'): + stroke = inkex.unittouu(style['stroke-width']) + stroke = int(stroke*self.scale) + if style.has_key('fill'): + if style['fill'] and style['fill'] != 'none' and style['fill'][0:3] != 'url': + fill = simplestyle.parseColor(style['fill']) + fillcolor = fill[0] + 256*fill[1] + 256*256*fill[2] + color = rgb[0] + 256*rgb[1] + 256*256*rgb[2] + if node.tag == inkex.addNS('path','svg'): + d = node.get('d') + if not d: + return + p = cubicsuperpath.parsePath(d) + elif node.tag == inkex.addNS('rect','svg'): + x = float(node.get('x')) + y = float(node.get('y')) + width = float(node.get('width')) + height = float(node.get('height')) + p = [[[x, y],[x, y],[x, y]]] + p.append([[x + width, y],[x + width, y],[x + width, y]]) + p.append([[x + width, y + height],[x + width, y + height],[x + width, y + height]]) + p.append([[x, y + height],[x, y + height],[x, y + height]]) + p.append([[x, y],[x, y],[x, y]]) + p = [p] + else: + return + trans = node.get('transform') + if trans: + mat = simpletransform.composeTransform(mat, simpletransform.parseTransform(trans)) + simpletransform.applyTransformToPath(mat, p) + hPen = mygdi.CreatePen(0, stroke, color) + mygdi.SelectObject(self.hDC, hPen) + self.emit_path(p) + if fillcolor is not None: + brush = LOGBRUSH(0, fillcolor, 0) + hBrush = mygdi.CreateBrushIndirect(addressof(brush)) + mygdi.SelectObject(self.hDC, hBrush) + mygdi.BeginPath(self.hDC) + self.emit_path(p) + mygdi.EndPath(self.hDC) + mygdi.FillPath(self.hDC) + return + + def emit_path(self, p): + for sub in p: + mygdi.MoveToEx(self.hDC, int(sub[0][1][0]), int(sub[0][1][1]), None) + POINTS = c_long*(6*(len(sub)-1)) + points = POINTS() + for i in range(len(sub)-1): + points[6*i] = int(sub[i][2][0]) + points[6*i + 1] = int(sub[i][2][1]) + points[6*i + 2] = int(sub[i + 1][0][0]) + points[6*i + 3] = int(sub[i + 1][0][1]) + points[6*i + 4] = int(sub[i + 1][1][0]) + points[6*i + 5] = int(sub[i + 1][1][1]) + mygdi.PolyBezierTo(self.hDC, addressof(points), 3*(len(sub)-1)) + return + + def process_clone(self, node): + trans = node.get('transform') + x = node.get('x') + y = node.get('y') + mat = [[1.0, 0.0, 0.0], [0.0, 1.0, 0.0]] + if trans: + mat = simpletransform.composeTransform(mat, simpletransform.parseTransform(trans)) + if x: + mat = simpletransform.composeTransform(mat, [[1.0, 0.0, float(x)], [0.0, 1.0, 0.0]]) + if y: + mat = simpletransform.composeTransform(mat, [[1.0, 0.0, 0.0], [0.0, 1.0, float(y)]]) + # push transform + if trans or x or y: + self.groupmat.append(simpletransform.composeTransform(self.groupmat[-1], mat)) + # get referenced node + refid = node.get(inkex.addNS('href','xlink')) + refnode = self.getElementById(refid[1:]) + if refnode is not None: + if refnode.tag == inkex.addNS('g','svg'): + self.process_group(refnode) + elif refnode.tag == inkex.addNS('use', 'svg'): + self.process_clone(refnode) + else: + self.process_shape(refnode, self.groupmat[-1]) + # pop transform + if trans or x or y: + self.groupmat.pop() + + def process_group(self, group): + if group.get(inkex.addNS('groupmode', 'inkscape')) == 'layer': + style = group.get('style') + if style: + style = simplestyle.parseStyle(style) + if style.has_key('display'): + if style['display'] == 'none' and self.visibleLayers: + return + trans = group.get('transform') + if trans: + self.groupmat.append(simpletransform.composeTransform(self.groupmat[-1], simpletransform.parseTransform(trans))) + for node in group: + if node.tag == inkex.addNS('g','svg'): + self.process_group(node) + elif node.tag == inkex.addNS('use', 'svg'): + self.process_clone(node) + else: + self.process_shape(node, self.groupmat[-1]) + if trans: + self.groupmat.pop() + + def effect(self): + pcchBuffer = c_long() + myspool.GetDefaultPrinterA(None, byref(pcchBuffer)) # get length of printer name + pname = create_string_buffer(pcchBuffer.value) + myspool.GetDefaultPrinterA(pname, byref(pcchBuffer)) # get printer name + hPrinter = c_long() + if myspool.OpenPrinterA(pname.value, byref(hPrinter), None) == 0: + exit(_("Failed to open default printer")) + + # get printer properties dialog + + pcchBuffer = myspool.DocumentPropertiesA(0, hPrinter, pname, None, None, 0) + pDevMode = create_string_buffer(pcchBuffer + 100) # allocate extra just in case + pcchBuffer = myspool.DocumentPropertiesA(0, hPrinter, pname, byref(pDevMode), None, DM_IN_PROMPT + DM_OUT_BUFFER) + myspool.ClosePrinter(hPrinter) + if pcchBuffer != 1: # user clicked Cancel + exit() + + # initiallize print document + + docname = self.document.getroot().xpath('@sodipodi:docname', namespaces=inkex.NSS) + if not docname: + docname = ['New document 1'] + lpszDocName = create_string_buffer('Inkscape ' + docname[0].split('\\')[-1]) + DOCINFO = c_long*5 + docInfo = DOCINFO(20, addressof(lpszDocName), 0, 0, 0) + self.hDC = mygdi.CreateDCA(None, pname, None, byref(pDevMode)) + if mygdi.StartDocA(self.hDC, byref(docInfo)) < 0: + exit() # user clicked Cancel + + self.scale = (ord(pDevMode[58]) + 256.0*ord(pDevMode[59]))/90 # use PrintQuality from DEVMODE + self.groupmat = [[[self.scale, 0.0, 0.0], [0.0, self.scale, 0.0]]] + doc = self.document.getroot() + self.process_group(doc) + mygdi.EndDoc(self.hDC) + +if __name__ == '__main__': + e = MyEffect() + e.affect() + +# vim: expandtab shiftwidth=4 tabstop=8 softtabstop=4 fileencoding=utf-8 textwidth=99 |
