-//
-// based on work by http://davidwalsh.name/convert-canvas-image
+//
+// based on work by http://davidwalsh.name/convert-canvas-image
// and http://getcontext.net/read/svg-images-on-a-html5-canvas
//
// This program is free software: you can redistribute it and/or modify
@@ -20,12 +20,12 @@
Snap.plugin(function (Snap, Element, Paper, global) {
-
-
+
+
/**
* @param {elem} elem start point
- *
+ *
* @returns {path}
*/
@@ -34,7 +34,7 @@ Snap.plugin(function (Snap, Element, Paper, global) {
var selection = [];
var children = elem.children();
-
+
if (children.length > 0) {
var goRecursive = (elem.type !== "defs" && // ignore these tags
elem.type !== "clipPath" &&
@@ -42,7 +42,7 @@ Snap.plugin(function (Snap, Element, Paper, global) {
elem.type !== "rdf:rdf" &&
elem.type !== "cc:work" &&
elem.type !== "sodipodi:namedview");
-
+
if(goRecursive) {
for (var i = 0; i < children.length; i++) {
var child = children[i];
@@ -50,7 +50,7 @@ Snap.plugin(function (Snap, Element, Paper, global) {
}
}
} else {
- if(elem.type === 'image'){
+ if(elem.type === 'image' || elem.type === "text" || elem.type === "#text"){
selection.push(elem);
} else {
if(fillPaths && elem.is_filled()){
@@ -65,7 +65,7 @@ Snap.plugin(function (Snap, Element, Paper, global) {
Element.prototype.is_filled = function(){
var elem = this;
-
+
// TODO text support
// TODO opacity support
if (elem.type !== "circle" &&
@@ -74,14 +74,17 @@ Snap.plugin(function (Snap, Element, Paper, global) {
elem.type !== "line" &&
elem.type !== "polygon" &&
elem.type !== "polyline" &&
- elem.type !== "path" ){
-
+ elem.type !== "path" //&&
+ // elem.type !== "text" &&
+ // elem.type !== "#text"
+ ){
+
return false;
}
-
+
var fill = elem.attr('fill');
var opacity = elem.attr('fill-opacity');
-
+
if(fill !== 'none'){
if(opacity === null || opacity > 0){
return true;
@@ -89,7 +92,7 @@ Snap.plugin(function (Snap, Element, Paper, global) {
}
return false;
};
-
+
Element.prototype.embedImage = function(callback){
var elem = this;
if(elem.type !== 'image') return;
@@ -113,15 +116,15 @@ Snap.plugin(function (Snap, Element, Paper, global) {
};
image.src = url;
-
+
};
-
+
Element.prototype.renderPNG = function (wMM, hMM, pxPerMM, callback) {
var elem = this;
// get svg as dataUrl
var svgStr = elem.outerSVG();
- var svgDataUri = 'data:image/svg+xml;base64,' + window.btoa(svgStr);
+ var svgDataUri = 'data:image/svg+xml;base64,' + window.btoa(unescape(encodeURIComponent(svgStr))); //deprecated unescape needed!
var source = new Image();
source.src = svgDataUri;
@@ -129,7 +132,7 @@ Snap.plugin(function (Snap, Element, Paper, global) {
var renderCanvas = document.createElement('canvas');
renderCanvas.id = "renderCanvas";
renderCanvas.width = wMM * pxPerMM;
- renderCanvas.height = hMM * pxPerMM;
+ renderCanvas.height = hMM * pxPerMM;
document.getElementsByTagName('body')[0].appendChild(renderCanvas);
var renderCanvasContext = renderCanvas.getContext('2d');
diff --git a/src/octoprint/plugins/svgtogcode/static/js/working_area.js b/src/octoprint/plugins/svgtogcode/static/js/working_area.js
index 8c320b95..79cc1685 100644
--- a/src/octoprint/plugins/svgtogcode/static/js/working_area.js
+++ b/src/octoprint/plugins/svgtogcode/static/js/working_area.js
@@ -107,6 +107,7 @@ $(function(){
self.clear = function(){
snap.selectAll('#userContent>*').remove();
snap.selectAll('#placedGcodes>*').remove();
+ snap.selectAll('rect:not(#coordGrid)').remove();
self.placedDesigns([]);
};
@@ -132,14 +133,9 @@ $(function(){
};
self.getXYCoord = function(evt){
- if(isFirefox) {
- var scale = evt.target.parentElement.transform.baseVal[0].matrix.a;
- var x = self.px2mm(evt.offsetX) * scale;
- var y = self.px2mm(parseFloat(evt.target.attributes.height.value) - evt.offsetY) * scale;
- } else {
- var x = self.px2mm(evt.offsetX);
- var y = self.px2mm(evt.target.ownerSVGElement.getBoundingClientRect().height - evt.offsetY); // hopefully this works across browsers
- }
+ var scale = evt.target.parentElement.transform.baseVal[0].matrix.a;
+ var x = self.px2mm(evt.offsetX) * scale;
+ var y = self.px2mm(parseFloat(evt.target.attributes.height.value) - evt.offsetY) * scale;
x = Math.min(x, self.workingAreaWidthMM());
y = Math.min(y, self.workingAreaHeightMM());
return {x:x, y:y};
@@ -241,11 +237,26 @@ $(function(){
var url = self._getSVGserveUrl(file);
callback = function (f) {
var newSvgAttrs = {};
- var root_attrs = f.select('svg').node.attributes;
+ if(f.select('svg') == null){
+ root_attrs = f.node.attributes;
+ } else {
+ var root_attrs = f.select('svg').node.attributes;
+ }
var doc_width = null;
var doc_height = null;
var doc_viewbox = null;
+ // find clippath elements
+ var clipPathEl = f.selectAll('clipPath');
+ if(clipPathEl.length != 0){
+ console.warn("Warning: removed unsupported clipPath element in SVG");
+ self.svg_contains_clipPath_warning();
+ clipPathEl.remove()
+ }
+
+ // find all elements with "display=none" and remove them
+ f.selectAll("[display=none]").remove()
+
// iterate svg tag attributes
for(var i = 0; i < root_attrs.length; i++){
var attr = root_attrs[i];
@@ -261,9 +272,19 @@ $(function(){
}
}
+ // find Illustrator comment and notify
+ f.node.childNodes.forEach(function(entry) {
+ if(entry.nodeType == 8) { // Nodetype 8 = comment
+ if(entry.textContent.indexOf('Illustrator') > -1) {
+ new PNotify({title: gettext("Illustrator SVG Detected"), text: "Illustrator SVG detected! To preserve coorect scale, please go to the \'Settings\' menu and change the \'SVG dpi\' field under \'Plugins/Svg Conversion\' according to your file. And add it again.", type: "info", hide: false});
+ }
+ }
+ });
+
// scale matrix
var mat = self.getDocumentViewBoxMatrix(doc_width, doc_height, doc_viewbox);
- var scaleMatrixStr = new Snap.Matrix(mat[0][0],mat[0][1],mat[1][0],mat[1][1],mat[0][2],mat[1][2]).toTransformString();
+ var dpiscale = 90 / self.settings.settings.plugins.svgtogcode.svgDPI();
+ var scaleMatrixStr = new Snap.Matrix(mat[0][0],mat[0][1],mat[1][0],mat[1][1],mat[0][2],mat[1][2]).scale(dpiscale).toTransformString();
newSvgAttrs['transform'] = scaleMatrixStr;
var newSvg = snap.group(f.selectAll("svg>*"));
@@ -389,8 +410,20 @@ $(function(){
};
};
+
+ self.svg_contains_clipPath_warning = function(){
+ var error = "" + gettext("The SVG file contains clipPath elements. clipPath is not supported yet and has been removed from file.") + "
";
+ //error += pnotifyAdditionalInfo("" + data.jqXHR.responseText + " ");
+ new PNotify({
+ title: "clipPath elements removed",
+ text: error,
+ type: "warn",
+ hide: false
+ });
+ };
+
self.svg_contains_text_warning = function(svg){
- var error = "" + gettext("The svg file contains text elements. Please convert them to paths. Otherwise they will be ignored.") + "
";
+ var error = "" + gettext("The SVG file contains text elements. If you want to laser just their outlines, please convert them to paths. Otherwise they will be engraved with infill.") + "
";
//error += pnotifyAdditionalInfo("" + data.jqXHR.responseText + " ");
new PNotify({
title: "Text elements found",
@@ -398,7 +431,6 @@ $(function(){
type: "warn",
hide: false
});
- svg.selectAll('text,tspan').remove();
};
self.svg_misfitting_warning = function(svg, misfitting){
@@ -704,6 +736,16 @@ $(function(){
return snap.selectAll("#userContent image");
};
+ self.hasTextItems = function () {
+ if(snap.selectAll("#userContent tspan").length > 0 ||
+ snap.selectAll("#userContent text").length > 0 ||
+ snap.selectAll("userContent #text").length > 0) {
+ return true
+ }else{
+ return false
+ }
+ };
+
self.getPlacedGcodes = ko.computed(function() {
var gcodeFiles = [];
ko.utils.arrayForEach(self.placedDesigns(), function(design) {
@@ -826,7 +868,7 @@ $(function(){
for (var i = 0; i < fillings.length; i++) {
var item = fillings[i];
- if (item.type === 'image') {
+ if (item.type === 'image' || item.type === "text" || item.type === "#text") {
// remove filter effects on images for proper rendering
var style = item.attr('style');
if (style !== null) {
diff --git a/src/octoprint/plugins/svgtogcode/templates/svgtogcode.jinja2 b/src/octoprint/plugins/svgtogcode/templates/svgtogcode.jinja2
index 0eba6848..4f693105 100644
--- a/src/octoprint/plugins/svgtogcode/templates/svgtogcode.jinja2
+++ b/src/octoprint/plugins/svgtogcode/templates/svgtogcode.jinja2
@@ -18,7 +18,7 @@
- Sets the intensity of the laser. The more intensity the deeper the effect on the material.
+ Sets the intensity of the laser. The more intensity the deeper the effect on the material.
Cutting needs higher intensities than engraving.
The effect in general is dependent from the material and its color and surface.
@@ -33,8 +33,8 @@
- Sets the velocity of the laser head. The slower the movement the deeper the effect on the material.
- Cutting needs slower movement than engraving.
+ Sets the velocity of the laser head. The slower the movement the deeper the effect on the material.
+ Cutting needs slower movement than engraving.
The effect in general is dependent from the material and its color and surface.
@@ -56,11 +56,11 @@
Some (especially bright) materials require the laser to dwell a little until the surface has absorbed enough energy to be affected.
- This parameter sets the amount of time in milliseconds the movement is paused after the laser is switched on.
+ This parameter sets the amount of time in milliseconds the movement is paused after the laser is switched on.
If the result shows gaps in lines for example increase this value carefully. The higher the value the higher the risk of material ignition.
-
+
{{ _('Image engraving parameters:') }}
@@ -103,10 +103,10 @@
Pixel / raster engravings are done line by line. This sets the distance between the single lines.
- Smaller values allow finer engravings but require a more precise focus and are slower.
+ Smaller values allow finer engravings but require a more precise focus and are slower.
-
+
{{ _('Image Preprocessing') }}
before
@@ -114,22 +114,22 @@
-
+
-
+
{{ _('Contrast') }}
-
+
- Increases the image contrast before converting to gcode.
+ Increases the image contrast before converting to gcode.
-
+
{{ _('Sharpening') }}
@@ -137,10 +137,10 @@
- Sharpens the image before converting to gcode.
+ Sharpens the image before converting to gcode.
-
+
{{ _('Dithering') }}
@@ -149,8 +149,8 @@
- Converts the image to solely black and white pixels.
- Use this if the laser effect on your material is not able to transfer grayscales.
+ Converts the image to solely black and white pixels.
+ Use this if the laser effect on your material is not able to transfer grayscales.
@@ -185,4 +185,4 @@
{{ _('Cancel') }}
{{ _('Convert') }}
-
\ No newline at end of file
+
diff --git a/src/octoprint/printer/standard.py b/src/octoprint/printer/standard.py
index a10580dd..1e826c01 100644
--- a/src/octoprint/printer/standard.py
+++ b/src/octoprint/printer/standard.py
@@ -331,7 +331,7 @@ class Printer(PrinterInterface, comm.MachineComPrintCallback):
def position(self, x, y):
printer_profile = self._printerProfileManager.get_current_or_default()
movement_speed = min(printer_profile["axes"]["x"]["speed"], printer_profile["axes"]["y"]["speed"])
- self.commands(["G90", "G0 X%.3f Y%.3f F%d" % (x, y, movement_speed), "?"])
+ self.commands(["G90", "G0 X%.3f Y%.3f F%d" % (x, y, movement_speed)])
def _convert_rate_value(self, factor, min=0, max=200):
if not isinstance(factor, (int, float, long)):
diff --git a/src/octoprint/translations/de/LC_MESSAGES/messages.po b/src/octoprint/translations/de/LC_MESSAGES/messages.po
index 596d79a6..4dedd7e2 100644
--- a/src/octoprint/translations/de/LC_MESSAGES/messages.po
+++ b/src/octoprint/translations/de/LC_MESSAGES/messages.po
@@ -568,8 +568,8 @@ msgstr ""
"aktualisiert werden."
#: src/octoprint/plugins/softwareupdate/static/js/softwareupdate.js:131
-msgid "Update Available"
-msgstr "Aktualisierung verfügbar"
+msgid "Mr Beam Update Available"
+msgstr "Mr Beam Aktualisierung verfügbar"
#: src/octoprint/plugins/softwareupdate/static/js/softwareupdate.js:143
msgid "Ignore"
diff --git a/src/octoprint/util/comm_acc2.py b/src/octoprint/util/comm_acc2.py
index bb1556a3..15e39c28 100644
--- a/src/octoprint/util/comm_acc2.py
+++ b/src/octoprint/util/comm_acc2.py
@@ -88,7 +88,7 @@ class MachineCom(object):
self._finished_passes = 0
# regular expressions
- self._regex_command = re.compile("^\s*\$?([GM]\d+|[TH])")
+ self._regex_command = re.compile("^\s*\$?([GM]\d+|[THX])")
self._regex_feedrate = re.compile("F\d+", re.IGNORECASE)
self._regex_intensity = re.compile("S\d+", re.IGNORECASE)
@@ -147,7 +147,7 @@ class MachineCom(object):
elif line.startswith('['): # feedback message
self._handle_feedback_message(line)
elif line.startswith('Grb'): # Grbl startup message
- self._handle_startup_message()
+ self._handle_startup_message(line)
except:
self._logger.exception("Something crashed inside the monitoring loop, please report this to Mr. Beam")
errorMsg = "See octoprint.log for details"
@@ -406,7 +406,7 @@ class MachineCom(object):
elif line[1:].startswith('Dis'): # [Disabled]
pass
- def _handle_startup_message(self):
+ def _handle_startup_message(self, line):
if self.isOperational():
errorMsg = "Machine reset."
self._cmd = None
@@ -421,7 +421,14 @@ class MachineCom(object):
self._changeState(self.STATE_LOCKED)
eventManager().fire(Events.ERROR, {"error": self.getErrorString()})
else:
- self._onConnected(self.STATE_LOCKED)
+ versionMatch = re.search("Grbl (?P.+?)(_(?P[0-9a-f]{7})(?P-dirty)?)? \[.+\]", line)
+ if versionMatch:
+ versionDict = versionMatch.groupdict()
+ self._writeGrblVersionToFile(versionDict)
+ if self._compareGrblVersion(versionDict) is False:
+ self._flashGrbl()
+ else:
+ self._onConnected(self.STATE_LOCKED)
def _update_grbl_pos(self, line):
# line example:
@@ -617,7 +624,7 @@ class MachineCom(object):
params = ["avrdude", "-patmega328p", "-carduino", "-b" + str(self._baudrate), "-P" + str(self._port), "-D", "-Uflash:w:" + pathToGrblHex]
rc = subprocesscall(params)
- if rc is False:
+ if rc == 0:
self._log("successfully flashed new grbl version")
self._openSerial()
self._changeState(self.STATE_CONNECTING)
@@ -754,6 +761,10 @@ class MachineCom(object):
self._changeState(self.STATE_HOMING)
return cmd
+ def _gcode_X_sent(self, cmd, cmd_type=None):
+ self._changeState(self.STATE_HOMING) # TODO: maybe change to seperate $X mode
+ return cmd
+
def _gcode_Hold_sent(self, cmd, cmd_type=None):
self._changeState(self.STATE_PAUSED)
return cmd
@@ -1164,6 +1175,9 @@ class PrintingGcodeFileInformation(PrintingFileInformation):
if not os.path.exists(self._filename) or not os.path.isfile(self._filename):
raise IOError("File %s does not exist" % self._filename)
+
+ self._stripCommments()
+
self._size = os.stat(self._filename).st_size
self._pos = 0
@@ -1217,6 +1231,16 @@ class PrintingGcodeFileInformation(PrintingFileInformation):
self._logger.exception("Exception while processing line")
raise e
+ def _stripCommments(self):
+ dir = os.path.dirname(os.path.abspath(self._filename))
+ tmpfile = open(dir + '/gcode.tmp', 'w')
+ with open(self._filename, "r") as fileobject:
+ for line in fileobject:
+ if process_gcode_line(line) is not None:
+ tmpfile.write(line)
+ tmpfile.close()
+ self._filename = dir + '/gcode.tmp'
+
def convert_pause_triggers(configured_triggers):
triggers = {
"enable": [],
@@ -1281,6 +1305,7 @@ def serialList():
baselist = baselist \
+ glob.glob("/dev/ttyUSB*") \
+ glob.glob("/dev/ttyACM*") \
+ + glob.glob("/dev/ttyAMA*") \
+ glob.glob("/dev/tty.usb*") \
+ glob.glob("/dev/cu.*") \
+ glob.glob("/dev/cuaU*") \