Skip to content

Commit 2adfabf

Browse files
SW-1328 the text of the svgs will not be engraved (mrbeam#1523)
* SW-1328 Hide fast engraving advanced option * SW-1328 Fix MRBEAM_DEBUG_RENDERING debugging * SW-1328 Push tspan parent (text) to selection instead of tspan elements * SW-1328 Mark text elements as filled instead of tspan elements Tspan elements cannot be rendered alone without a text parent leading to some SVG text combinations to be skipped * SW-1328 Add SVG styling to all clusters * SW-1328 Refactor code and attach ticket IDs to the added TODOs * SW-1328 Fix typo
1 parent 9c08282 commit 2adfabf

File tree

4 files changed

+77
-49
lines changed

4 files changed

+77
-49
lines changed

octoprint_mrbeam/static/js/render_fills.js

Lines changed: 56 additions & 39 deletions
Original file line numberDiff line numberDiff line change
@@ -39,6 +39,7 @@ Snap.plugin(function (Snap, Element, Paper, global) {
3939
// TODO: better than checking children.length and a blacklist would be to refer to
4040
// Graphic Elements vs. Container Elements (see https://www.w3.org/TR/SVG/struct.html#TermContainerElement)
4141
// image is excluded here as <image ...>\n</image> has a child of type #text (== '\n')
42+
// text is excluded here as <tspan> cannot be rendered without a <text> parent
4243
const goRecursive = ![
4344
"image",
4445
"defs",
@@ -47,6 +48,7 @@ Snap.plugin(function (Snap, Element, Paper, global) {
4748
"rdf:rdf",
4849
"cc:work",
4950
"sodipodi:namedview",
51+
"text",
5052
].includes(elem.type);
5153

5254
if (children.length > 0 && goRecursive) {
@@ -57,43 +59,15 @@ Snap.plugin(function (Snap, Element, Paper, global) {
5759
);
5860
}
5961
} else {
60-
if (elem.type === "g") return []; // means empty group
61-
if (elem.type === "defs") return []; // means empty defs
62-
if (
63-
elem.type === "image" ||
64-
elem.type === "text" ||
65-
elem.type === "#text"
66-
) {
67-
if (elem.type === "#text") {
68-
if (elem.node.nodeValue.trim() !== "") {
69-
let parent = elem.parent();
70-
if (parent.type === "textPath") {
71-
parent = parent.parent();
72-
}
73-
parent.addClass(className);
74-
selection.push(parent);
75-
}
76-
} else if (elem.type === "text") {
77-
if (elem.node.nodeValue !== null) {
78-
elem.addClass(className);
79-
selection.push(elem);
80-
}
81-
} else if (elem.type === "image") {
82-
elem.addClass(className);
83-
selection.push(elem);
84-
}
62+
let processedElem = processElementByType(
63+
elem,
64+
className,
65+
fillPaths
66+
);
67+
if (Array.isArray(processedElem) && processedElem.length === 0) {
68+
return [];
8569
} else {
86-
// check for non-dimensional elements and out of working area elements
87-
const bb = elem.getBBox();
88-
if (bb.w === 0 || bb.h === 0) {
89-
console.warn(`Element did not have expanse: ${elem.type}`);
90-
return [];
91-
}
92-
93-
if (fillPaths && elem.is_filled()) {
94-
elem.addClass(className);
95-
selection.push(elem);
96-
}
70+
selection.push(processedElem);
9771
}
9872
}
9973
return selection;
@@ -343,9 +317,8 @@ Snap.plugin(function (Snap, Element, Paper, global) {
343317

344318
elem.embedAllImages();
345319
const fontSet = elem.getUsedFonts();
346-
const fontDeclarations = WorkingAreaHelper.getFontDeclarations(
347-
fontSet
348-
);
320+
const fontDeclarations =
321+
WorkingAreaHelper.getFontDeclarations(fontSet);
349322

350323
let bboxMargin = 0;
351324
if (margin === null) {
@@ -700,4 +673,48 @@ Snap.plugin(function (Snap, Element, Paper, global) {
700673
else return Math.floor(bytes / (1024 * 1024)) + " MByte";
701674
}
702675
}
676+
677+
function processElementByType(elem, className, fillPaths) {
678+
if (elem.type === "g") return []; // means empty group
679+
if (elem.type === "defs") return []; // means empty defs
680+
// TODO: SW-1446
681+
if (elem.type === "#text") {
682+
if (elem.node.nodeValue.trim() !== "") {
683+
let parent = elem.parent();
684+
if (parent.type === "textPath") {
685+
parent = parent.parent();
686+
}
687+
parent.addClass(className);
688+
return parent;
689+
}
690+
} else if (elem.type === "text") {
691+
// check if <tspan> elements exist in <text> and if they contain any text
692+
const nonEmptyTspan = (child) =>
693+
child.nodeName === "tspan" && child.textContent !== null;
694+
// use node.textContent instead of node.nodeValue as nodeValue returns null regardless of valid fillings
695+
if (
696+
elem.node.textContent !== null ||
697+
Object.values(elem.node.childNodes).some(nonEmptyTspan)
698+
) {
699+
elem.addClass(className);
700+
return elem;
701+
}
702+
} else if (elem.type === "image") {
703+
elem.addClass(className);
704+
return elem;
705+
} else {
706+
// check for non-dimensional elements and out of working area elements
707+
const bb = elem.getBBox();
708+
if (bb.w === 0 || bb.h === 0) {
709+
console.warn(`Element did not have expanse: ${elem.type}`);
710+
return [];
711+
}
712+
713+
if (fillPaths && elem.is_filled()) {
714+
elem.addClass(className);
715+
return elem;
716+
}
717+
}
718+
return [];
719+
}
703720
});

octoprint_mrbeam/static/js/snap_helpers.js

Lines changed: 12 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -114,6 +114,7 @@ Snap.plugin(function (Snap, Element, Paper, global) {
114114
Element.prototype.toWorkingAreaSvgStr = function (
115115
w,
116116
h,
117+
fontDecl = "",
117118
styles = "",
118119
filter = null
119120
) {
@@ -124,8 +125,8 @@ Snap.plugin(function (Snap, Element, Paper, global) {
124125
const vb = ""; //att.viewBox.split(" ");
125126
const width = w; //vb[2];
126127
const height = h; // vb[3];
127-
if (Array.isArray(styles)) {
128-
styles = styles.join("\n");
128+
if (Array.isArray(fontDecl)) {
129+
fontDecl = fontDecl.join("\n");
129130
}
130131
const namespaces = new Set([
131132
'xmlns="http://www.w3.org/2000/svg"',
@@ -159,6 +160,7 @@ Snap.plugin(function (Snap, Element, Paper, global) {
159160
xxviewBox="${att.viewBox}">
160161
<defs>
161162
${defs}
163+
<style>${fontDecl}</style>
162164
<style>${styles}</style>
163165
</defs>
164166
${cnt}
@@ -171,12 +173,19 @@ Snap.plugin(function (Snap, Element, Paper, global) {
171173
Element.prototype.toWorkingAreaDataURL = function (
172174
w,
173175
h,
176+
fontDecl = "",
174177
styles = "",
175178
filter = null
176179
) {
177180
if (window && window.btoa) {
178181
const elem = this;
179-
const svg = elem.toWorkingAreaSvgStr(w, h, styles, filter);
182+
const svg = elem.toWorkingAreaSvgStr(
183+
w,
184+
h,
185+
fontDecl,
186+
styles,
187+
filter
188+
);
180189
const dataurl =
181190
"data:image/svg+xml;base64," +
182191
btoa(unescape(encodeURIComponent(svg)));

octoprint_mrbeam/static/js/working_area.js

Lines changed: 6 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -3222,7 +3222,9 @@ $(function () {
32223222
fillAreas,
32233223
pxPerMM
32243224
) {
3225+
// split SVG and get an array of clusters
32253226
let clusters = svg.splitRasterClusters(fillAreas);
3227+
32263228
// only render clusters overlapping the working area
32273229
const waBB = snap.select("#coordGrid").getBBox();
32283230
clusters = clusters.filter(function (c, idx) {
@@ -3234,13 +3236,16 @@ $(function () {
32343236
return intersects;
32353237
});
32363238

3239+
// get used fonts in text tags
32373240
const whitelist = svg.getUsedFonts();
3241+
// get font declarations for quickText fonts
32383242
const fontDecl = WorkingAreaHelper.getFontDeclarations(whitelist);
32393243
clusters = clusters.map((c) => {
32403244
c.svgDataUrl = svg.toWorkingAreaDataURL(
32413245
self.workingAreaWidthMM(),
32423246
self.workingAreaHeightMM(),
32433247
fontDecl,
3248+
svg.select("style")?.node?.innerHTML, // include SVG styling
32443249
`.toRaster.rasterCluster${c.idx}`
32453250
);
32463251
return c;
@@ -3249,11 +3254,7 @@ $(function () {
32493254
if (MRBEAM_DEBUG_RENDERING) {
32503255
debugBase64(
32513256
clusters.map((c) => {
3252-
c.svg.attr(
3253-
"viewBox",
3254-
`0 0 ${self.workingAreaWidthMM()} ${self.workingAreaHeightMM()}`
3255-
);
3256-
return c.svg.toDataURL();
3257+
return c.svgDataUrl;
32573258
}),
32583259
`Step 1: Raster Cluster SVGs`
32593260
);

octoprint_mrbeam/templates/conversion_dialog.jinja2

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -398,10 +398,11 @@
398398
id="parameter_assignment_engraving_mode_precise_btn"
399399
data-bind="event: {click: updateEngravingMode}"
400400
class="btn btn-default active">{{ _('Recommended') }}</button>
401-
<button type="button" value="fast"
401+
{# TODO: SW-1447 #}
402+
{#<button type="button" value="fast"
402403
id="parameter_assignment_engraving_mode_fast_btn"
403404
data-bind="event: {click: updateEngravingMode}"
404-
class="btn btn-default">{{ _('Fast') }}</button>
405+
class="btn btn-default">{{ _('Fast') }}</button>#}
405406
<button type="button" value="basic"
406407
id="parameter_assignment_engraving_mode_basic_btn"
407408
data-bind="event: {click: updateEngravingMode}"

0 commit comments

Comments
 (0)