Bugfixing Roland Cutstudio. Thanks to Max Gaukler
This commit is contained in:
parent
15e8907fbd
commit
2ec01ffc77
@ -23,7 +23,7 @@ Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
|||||||
'''
|
'''
|
||||||
|
|
||||||
# The source code is a horrible mess. I apologize for your inconvenience, but hope that it still helps. Feel free to improve :-)
|
# The source code is a horrible mess. I apologize for your inconvenience, but hope that it still helps. Feel free to improve :-)
|
||||||
|
# Keep everything python2 compatible as long as people out there are using Inkscape <= 0.92.4!
|
||||||
|
|
||||||
from __future__ import division
|
from __future__ import division
|
||||||
from __future__ import print_function
|
from __future__ import print_function
|
||||||
@ -41,9 +41,16 @@ import subprocess
|
|||||||
import shutil
|
import shutil
|
||||||
import numpy
|
import numpy
|
||||||
from functools import reduce
|
from functools import reduce
|
||||||
|
import atexit
|
||||||
|
import filecmp
|
||||||
|
try:
|
||||||
from pathlib import Path
|
from pathlib import Path
|
||||||
import inkex
|
except ImportError:
|
||||||
|
# Workaround for Python < 3.5
|
||||||
|
class fakepath:
|
||||||
|
def home(self):
|
||||||
|
return os.path.expanduser("~")
|
||||||
|
Path = fakepath()
|
||||||
try:
|
try:
|
||||||
from functools import lru_cache
|
from functools import lru_cache
|
||||||
except ImportError:
|
except ImportError:
|
||||||
@ -54,9 +61,12 @@ except ImportError:
|
|||||||
import tempfile
|
import tempfile
|
||||||
|
|
||||||
DEVNULL = open(os.devnull, 'w')
|
DEVNULL = open(os.devnull, 'w')
|
||||||
|
atexit.register(DEVNULL.close)
|
||||||
|
|
||||||
|
def message(s):
|
||||||
|
sys.stderr.write(s+"\n")
|
||||||
def debug(s):
|
def debug(s):
|
||||||
sys.stderr.write(s+"\n");
|
message(s)
|
||||||
|
|
||||||
# copied from https://github.com/t-oster/VisiCut/blob/0abe785a30d5d5085dd3b5953b38239b1ff83358/tools/inkscape_extension/visicut_export.py
|
# copied from https://github.com/t-oster/VisiCut/blob/0abe785a30d5d5085dd3b5953b38239b1ff83358/tools/inkscape_extension/visicut_export.py
|
||||||
def which(program, raiseError, extraPaths=[], subdir=None):
|
def which(program, raiseError, extraPaths=[], subdir=None):
|
||||||
@ -283,32 +293,40 @@ def EPS2CutstudioEPS(src, dest, mirror=False):
|
|||||||
return output(arr+[stack[-1]])
|
return output(arr+[stack[-1]])
|
||||||
def transform(x, y):
|
def transform(x, y):
|
||||||
#debug("trafo from: {} {}".format(x, y))
|
#debug("trafo from: {} {}".format(x, y))
|
||||||
p=numpy.matrix([[float(x),float(y),1]]).transpose()
|
p=numpy.array([[float(x),float(y),1]]).transpose()
|
||||||
multiply = lambda a, b: a*b
|
multiply = lambda a, b: numpy.matmul(a, b)
|
||||||
# concatenate transformations by multiplying: new = transformation x previousTransformtaion
|
# concatenate transformations by multiplying: new = transformation x previousTransformtaion
|
||||||
m=reduce(multiply, scalingStack[::-1])
|
m=reduce(multiply, scalingStack[::-1])
|
||||||
m=m.transpose()
|
m=m.transpose()
|
||||||
#debug("with {}".format(m))
|
#debug("with {}".format(m))
|
||||||
pnew=m*p
|
pnew = numpy.matmul(m, p)
|
||||||
x=float(pnew[0])
|
x=float(pnew[0])
|
||||||
y=float(pnew[1])
|
y=float(pnew[1])
|
||||||
#debug("to: {} {}".format(x, y))
|
#debug("to: {} {}".format(x, y))
|
||||||
return [x, y]
|
return [x, y]
|
||||||
|
def toString(v):
|
||||||
|
"""
|
||||||
|
like str(), but gives the exact same output for floats across python2 and python3
|
||||||
|
"""
|
||||||
|
if isinstance(v, (type(float()), type(int()))):
|
||||||
|
return repr(v)
|
||||||
|
else:
|
||||||
|
return str(v)
|
||||||
def outputMoveto(x, y):
|
def outputMoveto(x, y):
|
||||||
[xx, yy]=transform(x, y)
|
[xx, yy]=transform(x, y)
|
||||||
return output([str(xx), str(yy), "m"])
|
return output([toString(xx), toString(yy), "m"])
|
||||||
def outputLineto(x, y):
|
def outputLineto(x, y):
|
||||||
[xx, yy]=transform(x, y)
|
[xx, yy]=transform(x, y)
|
||||||
return output([str(xx), str(yy), "l"])
|
return output([toString(xx), toString(yy), "l"])
|
||||||
def output(array):
|
def output(array):
|
||||||
array=list(map(str, array))
|
array=list(map(toString, array))
|
||||||
output=" ".join(array)
|
output=" ".join(array)
|
||||||
#debug("OUTPUT: "+output)
|
#debug("OUTPUT: "+output)
|
||||||
return output + "\n"
|
return output + "\n"
|
||||||
stack=[]
|
stack=[]
|
||||||
scalingStack=[numpy.matrix(numpy.identity(3))]
|
scalingStack=[numpy.identity(3)]
|
||||||
if mirror:
|
if mirror:
|
||||||
scalingStack.append(numpy.matrix(numpy.diag([-1, 1, 1])))
|
scalingStack.append(numpy.diag([-1, 1, 1]))
|
||||||
lastMoveCoordinates=None
|
lastMoveCoordinates=None
|
||||||
outputStr=prefix
|
outputStr=prefix
|
||||||
inputFile=open(src)
|
inputFile=open(src)
|
||||||
@ -344,11 +362,11 @@ def EPS2CutstudioEPS(src, dest, mirror=False):
|
|||||||
outputStr += outputLineto(x, y+dy)
|
outputStr += outputLineto(x, y+dy)
|
||||||
outputStr += outputLineto(x, y)
|
outputStr += outputLineto(x, y)
|
||||||
elif item=="cm": # matrix transformation
|
elif item=="cm": # matrix transformation
|
||||||
newTrafo=numpy.matrix([[float(stack[-7]), float(stack[-6]), 0], [float(stack[-5]), float(stack[-4]), 0], [float(stack[-3]), float(stack[-2]), 1]])
|
newTrafo=numpy.array([[float(stack[-7]), float(stack[-6]), 0], [float(stack[-5]), float(stack[-4]), 0], [float(stack[-3]), float(stack[-2]), 1]])
|
||||||
#debug("applying trafo "+str(newTrafo))
|
#debug("applying trafo "+str(newTrafo))
|
||||||
scalingStack[-1]*=newTrafo
|
scalingStack[-1] = numpy.matmul(scalingStack[-1], newTrafo)
|
||||||
elif item=="q": # save graphics state to stack
|
elif item=="q": # save graphics state to stack
|
||||||
scalingStack.append(numpy.matrix(numpy.identity(3)))
|
scalingStack.append(numpy.identity(3))
|
||||||
elif item=="Q": # pop graphics state from stack
|
elif item=="Q": # pop graphics state from stack
|
||||||
scalingStack.pop()
|
scalingStack.pop()
|
||||||
elif item in ["m", "l"]:
|
elif item in ["m", "l"]:
|
||||||
@ -379,7 +397,8 @@ for arg in sys.argv[1:]:
|
|||||||
selectedElements +=[arg[5:]]
|
selectedElements +=[arg[5:]]
|
||||||
else:
|
else:
|
||||||
filename = arg
|
filename = arg
|
||||||
|
if "--selftest" in sys.argv:
|
||||||
|
filename = "./test-input.svg"
|
||||||
|
|
||||||
if len(selectedElements)==0:
|
if len(selectedElements)==0:
|
||||||
shutil.copyfile(filename, filename+".filtered.svg")
|
shutil.copyfile(filename, filename+".filtered.svg")
|
||||||
@ -395,27 +414,46 @@ else:
|
|||||||
cmd = [INKSCAPEBIN, "-T", "--export-ignore-filters", "--export-area-drawing", "--export-filename="+filename+".inkscape.eps", filename+".filtered.svg"]
|
cmd = [INKSCAPEBIN, "-T", "--export-ignore-filters", "--export-area-drawing", "--export-filename="+filename+".inkscape.eps", filename+".filtered.svg"]
|
||||||
inkscape_eps_file = filename + ".inkscape.eps"
|
inkscape_eps_file = filename + ".inkscape.eps"
|
||||||
|
|
||||||
#inkex.utils.debug(" ".join(cmd), file=sys.stderr)
|
#debug(" ".join(cmd))
|
||||||
assert 0 == subprocess.call(cmd, stderr=DEVNULL), 'EPS conversion failed: command returned error: ' + '"' + '" "'.join(cmd) + '"'
|
assert 0 == subprocess.call(cmd, stderr=DEVNULL), 'EPS conversion failed: command returned error: ' + '"' + '" "'.join(cmd) + '"'
|
||||||
assert os.path.exists(inkscape_eps_file), 'EPS conversion failed: command did not create result file: ' + '"' + '" "'.join(cmd) + '"'
|
assert os.path.exists(inkscape_eps_file), 'EPS conversion failed: command did not create result file: ' + '"' + '" "'.join(cmd) + '"'
|
||||||
|
|
||||||
EPS2CutstudioEPS(inkscape_eps_file, filename+".cutstudio.eps", mirror=("--mirror=true" in sys.argv))
|
|
||||||
|
if "--selftest" in sys.argv:
|
||||||
|
# used for unit-testing: fixed location of output file
|
||||||
|
destination = "./test-output-actual.cutstudio.eps"
|
||||||
|
else:
|
||||||
|
# normally
|
||||||
|
destination = filename + ".cutstudio.eps"
|
||||||
|
|
||||||
|
EPS2CutstudioEPS(inkscape_eps_file, destination, mirror=("--mirror=true" in sys.argv))
|
||||||
|
|
||||||
|
if "--selftest" in sys.argv:
|
||||||
|
# unittest: compare with known reference output
|
||||||
|
TEST_REFERENCE_FILE = "./test-output-reference.cutstudio.eps"
|
||||||
|
assert filecmp.cmp(destination, TEST_REFERENCE_FILE), "Test output changed. Please compare " + destination + " and " + TEST_REFERENCE_FILE
|
||||||
|
print("Selftest successful :-)")
|
||||||
|
sys.exit(0)
|
||||||
|
|
||||||
if os.name=="nt":
|
if os.name=="nt":
|
||||||
DETACHED_PROCESS = 8 # start as "daemon"
|
DETACHED_PROCESS = 8 # start as "daemon"
|
||||||
Popen([which("CutStudio\CutStudio.exe", True), "/import", filename+".cutstudio.eps"], creationflags=DETACHED_PROCESS, close_fds=True)
|
Popen([which("CutStudio\CutStudio.exe", True), "/import", destination], creationflags=DETACHED_PROCESS, close_fds=True)
|
||||||
else: #check if we have access to "wine"
|
else: #check if we have access to "wine"
|
||||||
if which("wine", False) is not None:
|
CUTSTUDIO_C_DRIVE = str(Path.home()) + "/.wine/drive_c/"
|
||||||
if which("CutStudio.exe", False, [str(Path.home()) + "/.wine/drive_c/Program Files (x86)/CutStudio"]) is not None:
|
CUTSTUDIO_PATH_LINUX_WINE = CUTSTUDIO_C_DRIVE + "Program Files (x86)/CutStudio/CutStudio.exe"
|
||||||
shutil.copyfile(filename + ".cutstudio.eps", str(Path.home()) + "/.wine/drive_c/cutstudio.eps")
|
CUTSTUDIO_COMMANDLINE = ["wine", CUTSTUDIO_PATH_LINUX_WINE, "/import", r'C:\cutstudio.eps']
|
||||||
inkex.utils.debug(str(Path.home()) + "/.wine/drive_c/'Program Files (x86)'/CutStudio/CutStudio.exe /import C:\\cutstudio.eps")
|
try:
|
||||||
with os.popen("wine " + str(Path.home()) + "/.wine/drive_c/'Program Files (x86)'/CutStudio/CutStudio.exe /import C:\\cutstudio.eps", "r") as cutstudio:
|
if not which("wine", False):
|
||||||
result = cutstudio.read()
|
raise Exception("Cannot find 'wine'")
|
||||||
else:
|
if not os.path.exists(CUTSTUDIO_PATH_LINUX_WINE):
|
||||||
inkex.utils.debug("Found a wine installation on your system but no CutStudio.exe. You can easily emulate this Windows application on Linux using wine. To do this provide a valid CutStudio installation in directory \"$HOME/.wine/drive_c/'Program Files (x86)'/CutStudio/CutStudio.exe\". The wine emulation was tested to work properly with Roland CutStudio version 3.10. For now your file was saved to:\n" + filename + ".cutstudio.eps")
|
raise Exception("Cannot find CutStudio in " + CUTSTUDIO_PATH_LINUX_WINE)
|
||||||
#os.popen("/usr/bin/xdg-open " + filename)
|
shutil.copyfile(destination, CUTSTUDIO_C_DRIVE + "cutstudio.eps")
|
||||||
else:
|
subprocess.check_call(CUTSTUDIO_COMMANDLINE)
|
||||||
inkex.utils.debug("Your file was saved to:\n" + filename + ".cutstudio.eps" + "\n Please open that with CutStudio manually. Tip: install wine on your system and use it to install CutStudio on Linux. This InkScape extension will automatically detect it. It allows you to directly import the exported InkScape file into CutStudio.")
|
except Exception as exc:
|
||||||
|
message("Could not open CutStudio.\nInstead, your file was saved to:\n" + destination + "\n" + \
|
||||||
|
"Please open that with CutStudio manually. \n\n" + \
|
||||||
|
"Tip: On Linux, you can use 'wine' to install CutStudio 3.10. Then, the file will be directly opened with CutStudio. \n" + \
|
||||||
|
" Diagnostic information: \n" + str(exc))
|
||||||
#os.popen("/usr/bin/xdg-open " + filename)
|
#os.popen("/usr/bin/xdg-open " + filename)
|
||||||
#Popen(["inkscape", filename+".filtered.svg"], stderr=DEVNULL)
|
#Popen(["inkscape", filename+".filtered.svg"], stderr=DEVNULL)
|
||||||
#Popen(["inkscape", filename+".cutstudio.eps"])
|
#Popen(["inkscape", filename+".cutstudio.eps"])
|
||||||
|
Reference in New Issue
Block a user