simplified "open in roland cutstudio"
This commit is contained in:
parent
06f96fe1e5
commit
ab25f2ad94
@ -22,49 +22,34 @@ along with this program; if not, write to the Free Software
|
||||
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 :-)
|
||||
# Keep everything python2 compatible as long as people out there are using Inkscape <= 0.92.4!
|
||||
'''
|
||||
KNOWN BUGS:
|
||||
WONTFIX: clipping of paths doesnt work
|
||||
WONTFIX: if there is any object with opacity != 100%, inkscape exports some objects as bitmaps. They will disappear in CutStudio! The same problem also occurs if the alpha value of stroke or fill color is not 100%.
|
||||
WONTFIX: filters (e.g. blur) are not supported
|
||||
'''
|
||||
|
||||
from __future__ import division
|
||||
from __future__ import print_function
|
||||
from __future__ import unicode_literals
|
||||
from __future__ import absolute_import
|
||||
|
||||
from builtins import open
|
||||
from builtins import map
|
||||
from builtins import str
|
||||
from builtins import range
|
||||
import sys
|
||||
import os
|
||||
from subprocess import Popen
|
||||
import subprocess
|
||||
from subprocess import Popen
|
||||
from functools import reduce
|
||||
from pathlib import Path
|
||||
import shutil
|
||||
import numpy
|
||||
from functools import reduce
|
||||
import atexit
|
||||
import filecmp
|
||||
try:
|
||||
from pathlib import Path
|
||||
except ImportError:
|
||||
# Workaround for Python < 3.5
|
||||
class fakepath:
|
||||
def home(self):
|
||||
return os.path.expanduser("~")
|
||||
Path = fakepath()
|
||||
try:
|
||||
from functools import lru_cache
|
||||
except ImportError:
|
||||
def lru_cache():
|
||||
def wrapper(func):
|
||||
return func
|
||||
return wrapper
|
||||
import tempfile
|
||||
import warnings
|
||||
import inkex.command
|
||||
from inkex.command import inkscape
|
||||
|
||||
DEVNULL = open(os.devnull, 'w')
|
||||
atexit.register(DEVNULL.close)
|
||||
|
||||
def message(s):
|
||||
sys.stderr.write(s+"\n")
|
||||
|
||||
def debug(s):
|
||||
message(s)
|
||||
|
||||
@ -93,18 +78,7 @@ def which(program, raiseError, extraPaths=[], subdir=None):
|
||||
raise Exception("Cannot find " + str(program) + " in any of these paths: " + str(pathlist) + ". Either the program is not installed, PATH is not set correctly, or this is a bug.")
|
||||
else:
|
||||
return None
|
||||
|
||||
# mostly copied from https://github.com/t-oster/VisiCut/blob/0abe785a30d5d5085dd3b5953b38239b1ff83358/tools/inkscape_extension/visicut_export.py
|
||||
@lru_cache()
|
||||
def inkscape_version():
|
||||
"""determine if Inkscape is version 0 or 1"""
|
||||
version = subprocess.check_output([INKSCAPEBIN, "--version"], stderr=DEVNULL).decode('ASCII', 'ignore')
|
||||
assert version.startswith("Inkscape ")
|
||||
if version.startswith("Inkscape 0"):
|
||||
return 0
|
||||
else:
|
||||
return 1
|
||||
|
||||
|
||||
# copied from https://github.com/t-oster/VisiCut/blob/0abe785a30d5d5085dd3b5953b38239b1ff83358/tools/inkscape_extension/visicut_export.py
|
||||
# Strip SVG to only contain selected elements, convert objects to paths, unlink clones
|
||||
# Inkscape version: takes care of special cases where the selected objects depend on non-selected ones.
|
||||
@ -115,72 +89,34 @@ def inkscape_version():
|
||||
def stripSVG_inkscape(src, dest, elements):
|
||||
# create temporary file for opening with inkscape.
|
||||
# delete this file later so that it will disappear from the "recently opened" list.
|
||||
tmpfile = tempfile.NamedTemporaryFile(delete=False, prefix='temp-visicut-', suffix='.svg')
|
||||
tmpfile = tempfile.NamedTemporaryFile(delete=False, prefix='temp-cutstudio-', suffix='.svg')
|
||||
tmpfile.close()
|
||||
tmpfile = tmpfile.name
|
||||
import shutil
|
||||
shutil.copyfile(src, tmpfile)
|
||||
actions_list=[]
|
||||
actions_list.append("ObjectToPath")
|
||||
actions_list.append("UnlockAllInAllLayers")
|
||||
|
||||
|
||||
if inkscape_version() == 0:
|
||||
# inkscape 0.92 long-term-support release. Will be in Linux distributions until 2025 or so
|
||||
# Selection commands: select items, invert selection, delete
|
||||
selection = []
|
||||
for el in elements:
|
||||
selection += ["--select=" + el]
|
||||
|
||||
if len(elements) > 0:
|
||||
# selection += ["--verb=FitCanvasToSelection"] # TODO add a user configuration option whether to keep the page size (and by this the position relative to the page)
|
||||
selection += ["--verb=EditInvertInAllLayers", "--verb=EditDelete"]
|
||||
|
||||
|
||||
hidegui = ["--without-gui"]
|
||||
|
||||
# currently this only works with gui because of a bug in inkscape: https://bugs.launchpad.net/inkscape/+bug/843260
|
||||
hidegui = []
|
||||
|
||||
command = [INKSCAPEBIN] + hidegui + [tmpfile, "--verb=UnlockAllInAllLayers", "--verb=UnhideAllInAllLayers"] + selection + ["--verb=EditSelectAllInAllLayers", "--verb=EditUnlinkClone", "--verb=ObjectToPath", "--verb=FileSave", "--verb=FileQuit"]
|
||||
if elements: # something is selected
|
||||
actions_list.append("select:{}".format(",".join(elements)))
|
||||
else:
|
||||
# Inkscape 1.0, to be released ca 2020
|
||||
# inkscape --select=... --verbs=...
|
||||
# (see inkscape --help, inkscape --verb-list)
|
||||
command = [INKSCAPEBIN, tmpfile, "--batch-process"]
|
||||
verbs = ["ObjectToPath", "UnlockAllInAllLayers"]
|
||||
if elements: # something is selected
|
||||
# --select=object1,object2,object3,...
|
||||
command += ["--select=" + ",".join(elements)]
|
||||
else:
|
||||
verbs += ["EditSelectAllInAllLayers"]
|
||||
verbs += ["UnhideAllInAllLayers", "EditInvertInAllLayers", "EditDelete", "EditSelectAllInAllLayers", "EditUnlinkClone", "ObjectToPath", "FileSave"]
|
||||
# --verb=action1;action2;...
|
||||
command += ["--verb=" + ";".join(verbs)]
|
||||
|
||||
|
||||
DEBUG = False
|
||||
if DEBUG:
|
||||
# Inkscape sometimes silently ignores wrong verbs, so we need to double-check that everything's right
|
||||
for verb in verbs:
|
||||
verb_list = [line.split(":")[0] for line in subprocess.check_output([INKSCAPEBIN, "--verb-list"], stderr=DEVNULL).split("\n")]
|
||||
if verb not in verb_list:
|
||||
sys.stderr.write("Inkscape does not have the verb '{}'. Please report this as a VisiCut bug.".format(verb))
|
||||
|
||||
inkscape_output = "(not yet run)"
|
||||
try:
|
||||
#sys.stderr.write(" ".join(command))
|
||||
# run inkscape, buffer output
|
||||
inkscape = subprocess.Popen(command, stdout=subprocess.PIPE, stderr=subprocess.STDOUT)
|
||||
inkscape_output = inkscape.communicate()[0]
|
||||
if inkscape.returncode != 0:
|
||||
sys.stderr.write("Error: cleaning the document with inkscape failed. Something might still be shown in visicut, but it could be incorrect.\nInkscape's output was:\n" + inkscape_output)
|
||||
except:
|
||||
sys.stderr.write("Error: cleaning the document with inkscape failed. Something might still be shown in visicut, but it could be incorrect. Exception information: \n" + str(sys.exc_info()[0]) + "Inkscape's output was:\n" + inkscape_output)
|
||||
|
||||
actions_list.append("EditSelectAllInAllLayers")
|
||||
actions_list.append("UnhideAllInAllLayers")
|
||||
actions_list.append("EditInvertInAllLayers")
|
||||
actions_list.append("EditDelete")
|
||||
actions_list.append("EditSelectAllInAllLayers")
|
||||
actions_list.append("EditUnlinkClone")
|
||||
actions_list.append("ObjectToPath")
|
||||
actions_list.append("FileSave")
|
||||
actions = ";".join(actions_list)
|
||||
cli_output = inkscape(tmpfile, "--batch-process", actions=actions) #process recent file
|
||||
if len(cli_output) > 0:
|
||||
self.msg("Inkscape returned the following output when trying to run the file export; the file export may still have worked:")
|
||||
self.msg(cli_output)
|
||||
|
||||
# move output to the intended destination filename
|
||||
os.rename(tmpfile, dest)
|
||||
|
||||
|
||||
|
||||
|
||||
# header
|
||||
# for debugging purposes you can open the resulting EPS file in Inkscape,
|
||||
# select all, ungroup multiple times
|
||||
@ -282,6 +218,7 @@ end restore
|
||||
"""
|
||||
|
||||
def OpenInRolandCutStudio(src, dest, mirror=False):
|
||||
|
||||
def outputFromStack(stack, n, transformCoordinates=True):
|
||||
arr=stack[-(n+1):-1]
|
||||
if transformCoordinates:
|
||||
@ -291,6 +228,7 @@ def OpenInRolandCutStudio(src, dest, mirror=False):
|
||||
return output(arrTransformed+[stack[-1]])
|
||||
else:
|
||||
return output(arr+[stack[-1]])
|
||||
|
||||
def transform(x, y):
|
||||
#debug("trafo from: {} {}".format(x, y))
|
||||
p=numpy.array([[float(x),float(y),1]]).transpose()
|
||||
@ -304,6 +242,7 @@ def OpenInRolandCutStudio(src, dest, mirror=False):
|
||||
y=float(pnew[1])
|
||||
#debug("to: {} {}".format(x, y))
|
||||
return [x, y]
|
||||
|
||||
def toString(v):
|
||||
"""
|
||||
like str(), but gives the exact same output for floats across python2 and python3
|
||||
@ -312,17 +251,21 @@ def OpenInRolandCutStudio(src, dest, mirror=False):
|
||||
return repr(v)
|
||||
else:
|
||||
return str(v)
|
||||
|
||||
def outputMoveto(x, y):
|
||||
[xx, yy]=transform(x, y)
|
||||
return output([toString(xx), toString(yy), "m"])
|
||||
|
||||
def outputLineto(x, y):
|
||||
[xx, yy]=transform(x, y)
|
||||
return output([toString(xx), toString(yy), "l"])
|
||||
|
||||
def output(array):
|
||||
array=list(map(toString, array))
|
||||
output=" ".join(array)
|
||||
#debug("OUTPUT: "+output)
|
||||
return output + "\n"
|
||||
|
||||
stack=[]
|
||||
scalingStack=[numpy.identity(3)]
|
||||
if mirror:
|
||||
@ -383,13 +326,6 @@ def OpenInRolandCutStudio(src, dest, mirror=False):
|
||||
outputFile.close()
|
||||
inputFile.close()
|
||||
|
||||
if os.name=="nt": # windows
|
||||
INKSCAPEBIN = which("inkscape.exe", True, subdir="Inkscape")
|
||||
else:
|
||||
INKSCAPEBIN=which("inkscape", True)
|
||||
|
||||
assert os.path.isfile(INKSCAPEBIN), "cannot find inkscape binary " + INKSCAPEBIN
|
||||
|
||||
selectedElements=[]
|
||||
for arg in sys.argv[1:]:
|
||||
if arg[0] == "-":
|
||||
@ -406,19 +342,21 @@ else:
|
||||
# only take selected elements
|
||||
stripSVG_inkscape(src=filename, dest=filename+".filtered.svg", elements=selectedElements)
|
||||
|
||||
if inkscape_version() == 0:
|
||||
# Inkscape 0.92.4
|
||||
cmd = [INKSCAPEBIN,"-z",filename+".filtered.svg","-T", "--export-ignore-filters", "--export-eps="+filename+".inkscape.eps"]
|
||||
else:
|
||||
# Inkscape 1.0
|
||||
cmd = [INKSCAPEBIN, "-T", "--export-ignore-filters", "--export-area-drawing", "--export-filename="+filename+".inkscape.eps", filename+".filtered.svg"]
|
||||
actions_list=[]
|
||||
actions_list.append("export-text-to-path")
|
||||
actions_list.append("export-ignore-filters")
|
||||
actions_list.append("export-area-drawing")
|
||||
actions_list.append("export-filename:{}".format(filename + ".inkscape.eps"))
|
||||
actions_list.append("export-do")
|
||||
actions = ";".join(actions_list)
|
||||
cli_output = inkscape(filename + ".filtered.svg", actions=actions) #process recent file
|
||||
if len(cli_output) > 0:
|
||||
self.msg("Inkscape returned the following output when trying to run the file export; the file export may still have worked:")
|
||||
self.msg(cli_output)
|
||||
|
||||
inkscape_eps_file = filename + ".inkscape.eps"
|
||||
|
||||
#debug(" ".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) + '"'
|
||||
|
||||
|
||||
if "--selftest" in sys.argv:
|
||||
# used for unit-testing: fixed location of output file
|
||||
destination = "./test-output-actual.cutstudio.eps"
|
||||
@ -437,7 +375,10 @@ if "--selftest" in sys.argv:
|
||||
|
||||
if os.name=="nt":
|
||||
DETACHED_PROCESS = 8 # start as "daemon"
|
||||
Popen([which("CutStudio\CutStudio.exe", True), "/import", destination], creationflags=DETACHED_PROCESS, close_fds=True)
|
||||
warnings.simplefilter('ignore', ResourceWarning) #suppress "enable tracemalloc to get the object allocation traceback"
|
||||
proc = Popen([which("CutStudio\CutStudio.exe", True), "/import", destination], creationflags=DETACHED_PROCESS, close_fds=True)
|
||||
#warnings.simplefilter("default", ResourceWarning)
|
||||
|
||||
else: #check if we have access to "wine"
|
||||
CUTSTUDIO_C_DRIVE = str(Path.home()) + "/.wine/drive_c/"
|
||||
CUTSTUDIO_PATH_LINUX_WINE = CUTSTUDIO_C_DRIVE + "Program Files (x86)/CutStudio/CutStudio.exe"
|
||||
@ -453,10 +394,4 @@ else: #check if we have access to "wine"
|
||||
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 is deprecated. Use subprocess.Popen
|
||||
#Popen(["inkscape", filename+".filtered.svg"], stderr=DEVNULL)
|
||||
#Popen(["inkscape", filename+".cutstudio.eps"])
|
||||
#os.unlink(filename+".filtered.svg")
|
||||
#os.unlink(filename)
|
||||
#os.unlink(filename+".cutstudio.eps")
|
||||
" Diagnostic information: \n" + str(exc))
|
Reference in New Issue
Block a user