meerk40t 0.9.7010__py2.py3-none-any.whl → 0.9.7030__py2.py3-none-any.whl
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- meerk40t/balormk/galvo_commands.py +1 -2
- meerk40t/core/cutcode/cutcode.py +1 -1
- meerk40t/core/cutplan.py +70 -2
- meerk40t/core/elements/branches.py +18 -4
- meerk40t/core/elements/element_treeops.py +43 -7
- meerk40t/core/elements/elements.py +49 -63
- meerk40t/core/elements/grid.py +8 -1
- meerk40t/core/elements/offset_clpr.py +4 -3
- meerk40t/core/elements/offset_mk.py +2 -1
- meerk40t/core/elements/shapes.py +379 -260
- meerk40t/core/elements/testcases.py +105 -0
- meerk40t/core/node/node.py +6 -3
- meerk40t/core/node/op_cut.py +9 -8
- meerk40t/core/node/op_dots.py +8 -8
- meerk40t/core/node/op_engrave.py +7 -7
- meerk40t/core/node/op_raster.py +8 -8
- meerk40t/core/planner.py +23 -0
- meerk40t/core/undos.py +1 -1
- meerk40t/core/wordlist.py +1 -0
- meerk40t/dxf/dxf_io.py +6 -0
- meerk40t/extra/encode_detect.py +8 -2
- meerk40t/extra/hershey.py +2 -3
- meerk40t/extra/inkscape.py +3 -5
- meerk40t/extra/mk_potrace.py +1959 -0
- meerk40t/extra/outerworld.py +2 -3
- meerk40t/extra/param_functions.py +2 -2
- meerk40t/extra/potrace.py +14 -10
- meerk40t/grbl/device.py +4 -1
- meerk40t/grbl/gui/grblcontroller.py +2 -2
- meerk40t/grbl/interpreter.py +1 -1
- meerk40t/gui/about.py +3 -5
- meerk40t/gui/basicops.py +3 -3
- meerk40t/gui/busy.py +75 -13
- meerk40t/gui/choicepropertypanel.py +365 -379
- meerk40t/gui/consolepanel.py +3 -3
- meerk40t/gui/gui_mixins.py +4 -1
- meerk40t/gui/hersheymanager.py +13 -3
- meerk40t/gui/laserpanel.py +12 -7
- meerk40t/gui/materialmanager.py +33 -6
- meerk40t/gui/plugin.py +9 -3
- meerk40t/gui/propertypanels/operationpropertymain.py +1 -1
- meerk40t/gui/ribbon.py +4 -1
- meerk40t/gui/scene/widget.py +1 -1
- meerk40t/gui/scenewidgets/rectselectwidget.py +19 -16
- meerk40t/gui/scenewidgets/selectionwidget.py +26 -20
- meerk40t/gui/simpleui.py +13 -8
- meerk40t/gui/simulation.py +22 -2
- meerk40t/gui/spoolerpanel.py +8 -11
- meerk40t/gui/themes.py +7 -1
- meerk40t/gui/tips.py +2 -3
- meerk40t/gui/toolwidgets/toolmeasure.py +4 -1
- meerk40t/gui/wxmeerk40t.py +32 -3
- meerk40t/gui/wxmmain.py +72 -6
- meerk40t/gui/wxmscene.py +95 -6
- meerk40t/gui/wxmtree.py +17 -11
- meerk40t/gui/wxutils.py +1 -1
- meerk40t/image/imagetools.py +21 -6
- meerk40t/kernel/kernel.py +31 -6
- meerk40t/kernel/settings.py +2 -0
- meerk40t/lihuiyu/device.py +9 -3
- meerk40t/main.py +22 -5
- meerk40t/network/console_server.py +52 -14
- meerk40t/network/web_server.py +15 -1
- meerk40t/ruida/device.py +5 -1
- meerk40t/ruida/gui/gui.py +6 -6
- meerk40t/ruida/gui/ruidaoperationproperties.py +1 -10
- meerk40t/ruida/rdjob.py +3 -3
- meerk40t/tools/geomstr.py +88 -0
- meerk40t/tools/polybool.py +2 -1
- meerk40t/tools/shxparser.py +92 -34
- {meerk40t-0.9.7010.dist-info → meerk40t-0.9.7030.dist-info}/METADATA +1 -1
- {meerk40t-0.9.7010.dist-info → meerk40t-0.9.7030.dist-info}/RECORD +77 -75
- {meerk40t-0.9.7010.dist-info → meerk40t-0.9.7030.dist-info}/WHEEL +1 -1
- {meerk40t-0.9.7010.dist-info → meerk40t-0.9.7030.dist-info}/LICENSE +0 -0
- {meerk40t-0.9.7010.dist-info → meerk40t-0.9.7030.dist-info}/entry_points.txt +0 -0
- {meerk40t-0.9.7010.dist-info → meerk40t-0.9.7030.dist-info}/top_level.txt +0 -0
- {meerk40t-0.9.7010.dist-info → meerk40t-0.9.7030.dist-info}/zip-safe +0 -0
@@ -26,6 +26,8 @@ def plugin(kernel, lifecycle=None):
|
|
26
26
|
command, channel, _, port=23, silent=False, quit=False, **kwargs
|
27
27
|
):
|
28
28
|
root = kernel.root
|
29
|
+
# Variable to store input
|
30
|
+
root.__console_buffer = ""
|
29
31
|
try:
|
30
32
|
server = root.open_as("module/TCPServer", "console-server", port=port)
|
31
33
|
if quit:
|
@@ -36,25 +38,61 @@ def plugin(kernel, lifecycle=None):
|
|
36
38
|
"{kernel_name} {kernel_version} Telnet Console.\r\n"
|
37
39
|
).format(kernel_name=kernel.name, kernel_version=kernel.version)
|
38
40
|
send.line_end = "\r\n"
|
39
|
-
|
40
41
|
recv = root.channel("console-server/recv")
|
41
|
-
|
42
|
-
channel(
|
43
|
-
|
44
|
-
|
45
|
-
|
46
|
-
|
42
|
+
except (OSError, ValueError):
|
43
|
+
channel(_("Server failed on port: {port}").format(port=port))
|
44
|
+
return
|
45
|
+
|
46
|
+
def exec_command(data: str) -> None:
|
47
|
+
# We are in a different thread, so let's hand over stuff to the gui
|
48
|
+
if isinstance(data, bytes):
|
49
|
+
try:
|
50
|
+
data = data.decode()
|
51
|
+
except UnicodeDecodeError as e:
|
52
|
+
return
|
53
|
+
start = 0
|
54
|
+
while True:
|
55
|
+
idx = data.find("|", start)
|
56
|
+
if idx < 0:
|
57
|
+
break
|
58
|
+
# Is the amount of quotation marks odd (ie non-even)?
|
59
|
+
# Yes: we are in the middle of a str
|
60
|
+
# No: we can split the command
|
61
|
+
quotations = data.count('"', 0, idx)
|
62
|
+
if quotations % 2 == 0:
|
63
|
+
data = data[:idx].rstrip() + "\n" + data[idx+1:].lstrip()
|
64
|
+
start = idx + 1
|
65
|
+
root.__console_buffer += data
|
66
|
+
while "\n" in root.__console_buffer:
|
67
|
+
pos = root.__console_buffer.find("\n")
|
68
|
+
command = root.__console_buffer[0:pos].strip("\r")
|
69
|
+
root.__console_buffer = root.__console_buffer[pos + 1 :]
|
70
|
+
if handover is None:
|
71
|
+
root.console(command + "\n")
|
72
|
+
else:
|
73
|
+
handover(command)
|
74
|
+
|
75
|
+
handover = None
|
76
|
+
for result in root.find("gui/handover"):
|
77
|
+
# Do we have a thread handover routine?
|
78
|
+
if result is not None:
|
79
|
+
handover, _path, suffix_path = result
|
80
|
+
break
|
81
|
+
recv.watch(exec_command)
|
82
|
+
|
83
|
+
channel(
|
84
|
+
_(
|
85
|
+
"{name} {version} console server on port: {port}".format(
|
86
|
+
name=kernel.name, version=kernel.version, port=port
|
47
87
|
)
|
48
88
|
)
|
89
|
+
)
|
49
90
|
|
50
|
-
|
51
|
-
|
52
|
-
|
53
|
-
|
91
|
+
if not silent:
|
92
|
+
console = root.channel("console")
|
93
|
+
console.watch(send)
|
94
|
+
server.events_channel.watch(console)
|
54
95
|
|
55
|
-
except (OSError, ValueError):
|
56
|
-
channel(_("Server failed on port: {port}").format(port=port))
|
57
|
-
return
|
58
96
|
|
59
97
|
@kernel.console_option(
|
60
98
|
"port", "p", type=int, default=2080, help=_("port to listen on.")
|
meerk40t/network/web_server.py
CHANGED
@@ -34,6 +34,13 @@ class WebServer(Module):
|
|
34
34
|
)
|
35
35
|
self.server_headers = dict()
|
36
36
|
self.client_headers = dict()
|
37
|
+
self.handover = None
|
38
|
+
root = self.context.root
|
39
|
+
for result in root.find("gui/handover"):
|
40
|
+
# Do we have a thread handover routine?
|
41
|
+
if result is not None:
|
42
|
+
self.handover, _path, suffix_path = result
|
43
|
+
break
|
37
44
|
|
38
45
|
def stop(self):
|
39
46
|
self.state = "terminate"
|
@@ -45,6 +52,13 @@ class WebServer(Module):
|
|
45
52
|
if self.socket is not None:
|
46
53
|
self.socket.close()
|
47
54
|
self.socket = None
|
55
|
+
|
56
|
+
def send(self, command):
|
57
|
+
if self.handover is None:
|
58
|
+
self.context(f"{command}\n")
|
59
|
+
else:
|
60
|
+
self.handover(command)
|
61
|
+
|
48
62
|
|
49
63
|
def receive(self, data):
|
50
64
|
def parse_received_data():
|
@@ -92,7 +106,7 @@ class WebServer(Module):
|
|
92
106
|
content = f"Received command: '{command}'"
|
93
107
|
elif self.client_headers["TYPE"] == "POST" and "post_cmd" in self.client_headers:
|
94
108
|
command = self.client_headers["post_cmd"]
|
95
|
-
self.
|
109
|
+
self.send(command)
|
96
110
|
content = f"Received command: '{command}'"
|
97
111
|
return content_type, content
|
98
112
|
|
meerk40t/ruida/device.py
CHANGED
@@ -263,18 +263,22 @@ class RuidaDevice(Service):
|
|
263
263
|
choice_dict["choices"] = ["UNCONFIGURED"]
|
264
264
|
choice_dict["display"] = ["pyserial-not-installed"]
|
265
265
|
|
266
|
+
from platform import system
|
267
|
+
is_linux = system() == "Linux"
|
268
|
+
|
266
269
|
choices = [
|
267
270
|
{
|
268
271
|
"attr": "serial_port",
|
269
272
|
"object": self,
|
270
273
|
"default": "UNCONFIGURED",
|
271
274
|
"type": str,
|
272
|
-
"style": "option",
|
275
|
+
"style": "combosmall" if is_linux else "option",
|
273
276
|
"label": "",
|
274
277
|
"tip": _("What serial interface does this device connect to?"),
|
275
278
|
"section": "_10_Serial Interface",
|
276
279
|
"subsection": "_00_",
|
277
280
|
"dynamic": update,
|
281
|
+
"exclusive": not is_linux,
|
278
282
|
},
|
279
283
|
{
|
280
284
|
"attr": "baud_rate",
|
meerk40t/ruida/gui/gui.py
CHANGED
@@ -48,7 +48,7 @@ def plugin(service, lifecycle):
|
|
48
48
|
|
49
49
|
from meerk40t.ruida.gui.ruidaconfig import RuidaConfiguration
|
50
50
|
from meerk40t.ruida.gui.ruidacontroller import RuidaController
|
51
|
-
from meerk40t.ruida.gui.ruidaoperationproperties import RuidaOperationPanel
|
51
|
+
# from meerk40t.ruida.gui.ruidaoperationproperties import RuidaOperationPanel
|
52
52
|
|
53
53
|
service.register("window/Controller", RuidaController)
|
54
54
|
service.register("window/Configuration", RuidaConfiguration)
|
@@ -56,11 +56,11 @@ def plugin(service, lifecycle):
|
|
56
56
|
service.register("winpath/Controller", service)
|
57
57
|
service.register("winpath/Configuration", service)
|
58
58
|
|
59
|
-
service.register("property/RasterOpNode/Ruida", RuidaOperationPanel)
|
60
|
-
service.register("property/CutOpNode/Ruida", RuidaOperationPanel)
|
61
|
-
service.register("property/EngraveOpNode/Ruida", RuidaOperationPanel)
|
62
|
-
service.register("property/ImageOpNode/Ruida", RuidaOperationPanel)
|
63
|
-
service.register("property/DotsOpNode/Ruida", RuidaOperationPanel)
|
59
|
+
# service.register("property/RasterOpNode/Ruida", RuidaOperationPanel)
|
60
|
+
# service.register("property/CutOpNode/Ruida", RuidaOperationPanel)
|
61
|
+
# service.register("property/EngraveOpNode/Ruida", RuidaOperationPanel)
|
62
|
+
# service.register("property/ImageOpNode/Ruida", RuidaOperationPanel)
|
63
|
+
# service.register("property/DotsOpNode/Ruida", RuidaOperationPanel)
|
64
64
|
|
65
65
|
service.add_service_delegate(RuidaGui(service))
|
66
66
|
|
@@ -17,16 +17,7 @@ class RuidaOperationPanel(ScrolledPanel):
|
|
17
17
|
self.parent = args[0]
|
18
18
|
self.operation = node
|
19
19
|
|
20
|
-
choices = [
|
21
|
-
{
|
22
|
-
"attr": "air_assist",
|
23
|
-
"object": node,
|
24
|
-
"default": True,
|
25
|
-
"type": bool,
|
26
|
-
"label": _("Air Assist"),
|
27
|
-
"tip": _("Trigger the per element air assist"),
|
28
|
-
},
|
29
|
-
]
|
20
|
+
choices = []
|
30
21
|
|
31
22
|
self.panel = ChoicePropertyPanel(
|
32
23
|
self, wx.ID_ANY, context=self.context, choices=choices, scrolling=False
|
meerk40t/ruida/rdjob.py
CHANGED
@@ -1376,13 +1376,13 @@ class RDJob:
|
|
1376
1376
|
part = current_settings.get("part", 0)
|
1377
1377
|
speed = current_settings.get("speed", 0)
|
1378
1378
|
power = current_settings.get("power", 0) / 10.0
|
1379
|
-
air = current_settings.get("
|
1379
|
+
air = current_settings.get("coolant", 0)
|
1380
1380
|
self.layer_end()
|
1381
1381
|
self.layer_number_part(part)
|
1382
1382
|
self.laser_device_0()
|
1383
|
-
if air:
|
1383
|
+
if air == 1:
|
1384
1384
|
self.air_assist_on()
|
1385
|
-
|
1385
|
+
elif air==2:
|
1386
1386
|
self.air_assist_off()
|
1387
1387
|
self.speed_laser_1(speed)
|
1388
1388
|
self.laser_on_delay(0)
|
meerk40t/tools/geomstr.py
CHANGED
@@ -179,6 +179,94 @@ def remove(s, i):
|
|
179
179
|
"""
|
180
180
|
s[i:-1] = s[i + 1 :]
|
181
181
|
|
182
|
+
def stitch_geometries(geometry_list:list, tolerance:float=0.0) -> list:
|
183
|
+
action_list = list(geometry_list)
|
184
|
+
result_list = []
|
185
|
+
start_points = []
|
186
|
+
end_points = []
|
187
|
+
anychanges = True
|
188
|
+
were_stitches = False
|
189
|
+
iteration_loop = 0
|
190
|
+
while anychanges:
|
191
|
+
iteration_loop += 1
|
192
|
+
# print (f"Loop {iteration_loop}")
|
193
|
+
anychanges = False
|
194
|
+
for g1 in action_list:
|
195
|
+
if g1 is None:
|
196
|
+
continue
|
197
|
+
fp1 = g1.first_point
|
198
|
+
lp1 = g1.last_point
|
199
|
+
if fp1 is None or lp1 is None:
|
200
|
+
continue
|
201
|
+
was_stitched = False
|
202
|
+
for idx, g2 in enumerate(result_list):
|
203
|
+
fp2 = start_points[idx]
|
204
|
+
lp2 = end_points[idx]
|
205
|
+
# end - start: append
|
206
|
+
# end - end : append reverse
|
207
|
+
# start - start: insert reverse
|
208
|
+
# start - end: insert
|
209
|
+
dist_e_s = abs(lp2 - fp1)
|
210
|
+
dist_e_e = abs(lp2 - lp1)
|
211
|
+
dist_s_s = abs(fp2 - fp1)
|
212
|
+
dist_s_e = abs(fp2 - lp1)
|
213
|
+
# print (f"test #{idx} ({fp1.real:.2f},{fp1.imag:.2f})->({lp1.real:.2f},{lp1.imag:.2f}) versus ({fp2.real:.2f},{fp2.imag:.2f})->({lp2.real:.2f},{lp2.imag:.2f})")
|
214
|
+
# print (f"Gaps: e -> s: {dist_e_s:.3f}, e -> e: {dist_e_e:.3f}, s -> s: {dist_s_s:.3f},s -> e: {dist_s_e:.3f},")
|
215
|
+
if dist_e_s <= tolerance:
|
216
|
+
# append
|
217
|
+
if dist_e_s > 0:
|
218
|
+
g2.line(lp2, fp1)
|
219
|
+
g2.append(g1, end=False)
|
220
|
+
was_stitched = True
|
221
|
+
elif dist_e_e <= tolerance:
|
222
|
+
# append reverse
|
223
|
+
g1.reverse()
|
224
|
+
if dist_e_e > 0:
|
225
|
+
g2.line(lp2, lp1)
|
226
|
+
g2.append(g1, end=False)
|
227
|
+
was_stitched = True
|
228
|
+
elif dist_s_s <= tolerance:
|
229
|
+
# insert reverse
|
230
|
+
g1.reverse()
|
231
|
+
if dist_s_s > 0:
|
232
|
+
g1.line(fp1, fp2)
|
233
|
+
g2.insert(0, g1.segments[:g1.index])
|
234
|
+
was_stitched = True
|
235
|
+
elif dist_s_e <= tolerance:
|
236
|
+
# insert
|
237
|
+
if dist_s_e > 0:
|
238
|
+
g1.line(lp1, fp2)
|
239
|
+
g2.insert(0, g1.segments[:g1.index])
|
240
|
+
was_stitched = True
|
241
|
+
if was_stitched:
|
242
|
+
# print ("stitched")
|
243
|
+
# g2.debug_me()
|
244
|
+
anychanges = True
|
245
|
+
start_points[idx] = g2.first_point
|
246
|
+
end_points[idx] = g2.last_point
|
247
|
+
result_list[idx] = g2
|
248
|
+
were_stitches = True
|
249
|
+
break
|
250
|
+
|
251
|
+
if not was_stitched:
|
252
|
+
# print ("Unchanged")
|
253
|
+
result_list.append(g1)
|
254
|
+
start_points.append(fp1)
|
255
|
+
end_points.append(lp1)
|
256
|
+
if anychanges:
|
257
|
+
action_list = list(result_list)
|
258
|
+
result_list.clear()
|
259
|
+
start_points.clear()
|
260
|
+
end_points.clear()
|
261
|
+
if were_stitches:
|
262
|
+
for g1 in result_list:
|
263
|
+
fp1 = g1.first_point
|
264
|
+
lp1 = g1.last_point
|
265
|
+
dist_e_s = abs(lp1 - fp1)
|
266
|
+
if 0 < dist_e_s <= tolerance:
|
267
|
+
g1.line(lp1, fp1)
|
268
|
+
return result_list
|
269
|
+
return None
|
182
270
|
|
183
271
|
class Simplifier:
|
184
272
|
# Copyright (c) 2014 Elliot Hallmark
|
meerk40t/tools/polybool.py
CHANGED
@@ -275,7 +275,8 @@ class LinkedList:
|
|
275
275
|
data.next = None
|
276
276
|
|
277
277
|
def remove_func():
|
278
|
-
data.previous
|
278
|
+
if data.previous is not None:
|
279
|
+
data.previous.next = data.next
|
279
280
|
if data.next is not None:
|
280
281
|
data.next.previous = data.previous
|
281
282
|
data.previous = None
|
meerk40t/tools/shxparser.py
CHANGED
@@ -229,6 +229,22 @@ class ShxFont:
|
|
229
229
|
self._parse_unifont(f)
|
230
230
|
else:
|
231
231
|
raise ShxFontParseError(f"{self.type} is not a valid shx file type.")
|
232
|
+
self.translate_names_to_codes()
|
233
|
+
|
234
|
+
def translate_names_to_codes(self):
|
235
|
+
# We can't properly deal with long names,
|
236
|
+
# so we translate them a virtual character
|
237
|
+
gdict = list(self.glyphs.items())
|
238
|
+
virtual_char = len(self.glyphs)
|
239
|
+
for key, data in gdict:
|
240
|
+
if isinstance(key, str) and len(key) > 1:
|
241
|
+
while True:
|
242
|
+
newkey = chr(virtual_char)
|
243
|
+
if newkey not in self.glyphs:
|
244
|
+
break
|
245
|
+
virtual_char += 1
|
246
|
+
self.glyphs[newkey] = data
|
247
|
+
del self.glyphs[key]
|
232
248
|
|
233
249
|
def _parse_header(self, f):
|
234
250
|
header = read_string(f)
|
@@ -351,6 +367,7 @@ class ShxFont:
|
|
351
367
|
try:
|
352
368
|
return self._code.pop()
|
353
369
|
except IndexError as e:
|
370
|
+
print (f"Error in {self.font_name}: no codes to pop")
|
354
371
|
raise ShxFontParseError("No codes to pop()") from e
|
355
372
|
|
356
373
|
def render(
|
@@ -471,7 +488,10 @@ class ShxFont:
|
|
471
488
|
line_lengths = _do_render(vtext, offsets)
|
472
489
|
|
473
490
|
def _parse_code(self):
|
474
|
-
|
491
|
+
try:
|
492
|
+
b = self.pop()
|
493
|
+
except ShxFontParseError:
|
494
|
+
return
|
475
495
|
direction = b & 0x0F
|
476
496
|
length = (b & 0xF0) >> 4
|
477
497
|
if length == 0:
|
@@ -608,7 +628,10 @@ class ShxFont:
|
|
608
628
|
|
609
629
|
:return:
|
610
630
|
"""
|
611
|
-
|
631
|
+
try:
|
632
|
+
factor = self.pop()
|
633
|
+
except ShxFontParseError:
|
634
|
+
return
|
612
635
|
if self._debug:
|
613
636
|
print(
|
614
637
|
f"DIVIDE_VECTOR {self._scale}/{factor} {'(Skipped)' if self._skip else ''}"
|
@@ -679,7 +702,10 @@ class ShxFont:
|
|
679
702
|
self._last_x, self._last_y = self._x, self._y
|
680
703
|
|
681
704
|
def _draw_subshape_shapes(self):
|
682
|
-
|
705
|
+
try:
|
706
|
+
subshape = self.pop()
|
707
|
+
except ShxFontParseError:
|
708
|
+
return
|
683
709
|
if self._debug:
|
684
710
|
print(
|
685
711
|
f"Appending glyph {subshape} (Type={self.type}). {'(Skipped)' if self._skip else ''}"
|
@@ -694,21 +720,28 @@ class ShxFont:
|
|
694
720
|
self._code += bytearray(reversed(shape))
|
695
721
|
|
696
722
|
def _draw_subshape_bigfont(self):
|
697
|
-
|
723
|
+
try:
|
724
|
+
subshape = self.pop()
|
725
|
+
except ShxFontParseError:
|
726
|
+
return
|
698
727
|
if self._debug:
|
699
728
|
print(
|
700
729
|
f"Appending glyph {subshape} (Type={self.type}). {'(Skipped)' if self._skip else ''}"
|
701
730
|
)
|
702
731
|
if subshape == 0:
|
703
|
-
|
704
|
-
|
705
|
-
|
706
|
-
|
707
|
-
|
708
|
-
|
709
|
-
|
710
|
-
|
711
|
-
|
732
|
+
try:
|
733
|
+
subshape = int_16le([self.pop(), self.pop()])
|
734
|
+
|
735
|
+
origin_x = self.pop() * self._scale
|
736
|
+
origin_y = self.pop() * self._scale
|
737
|
+
width = self.pop() * self._scale
|
738
|
+
height = self.pop() * self._scale
|
739
|
+
if self._debug:
|
740
|
+
print(
|
741
|
+
f"Extended Bigfont Glyph: {subshape}, origin_x = {origin_x}, origin_y = {origin_y}. {width}x{height}"
|
742
|
+
)
|
743
|
+
except ShxFontParseError:
|
744
|
+
return
|
712
745
|
if self._skip:
|
713
746
|
self._skip = False
|
714
747
|
return
|
@@ -719,7 +752,11 @@ class ShxFont:
|
|
719
752
|
self._code += bytearray(reversed(shape))
|
720
753
|
|
721
754
|
def _draw_subshape_unifont(self):
|
722
|
-
|
755
|
+
try:
|
756
|
+
subshape = int_16le([self.pop(), self.pop()])
|
757
|
+
except ShxFontParseError:
|
758
|
+
return
|
759
|
+
|
723
760
|
if self._debug:
|
724
761
|
print(
|
725
762
|
f"Appending glyph {subshape} (Type={self.type}). {'(Skipped)' if self._skip else ''}"
|
@@ -755,8 +792,12 @@ class ShxFont:
|
|
755
792
|
ranges from -128 to +127.
|
756
793
|
:return:
|
757
794
|
"""
|
758
|
-
|
759
|
-
|
795
|
+
try:
|
796
|
+
dx = signed8(self.pop()) * self._scale
|
797
|
+
dy = signed8(self.pop()) * self._scale
|
798
|
+
except ShxFontParseError:
|
799
|
+
return
|
800
|
+
|
760
801
|
if self._debug:
|
761
802
|
print(f"XY_DISPLACEMENT {dx} {dy} {'(Skipped)' if self._skip else ''}")
|
762
803
|
if self._skip:
|
@@ -777,8 +818,11 @@ class ShxFont:
|
|
777
818
|
:return:
|
778
819
|
"""
|
779
820
|
while True:
|
780
|
-
|
781
|
-
|
821
|
+
try:
|
822
|
+
dx = signed8(self.pop()) * self._scale
|
823
|
+
dy = signed8(self.pop()) * self._scale
|
824
|
+
except ShxFontParseError:
|
825
|
+
return
|
782
826
|
if self._debug:
|
783
827
|
print(
|
784
828
|
f"POLY_XY_DISPLACEMENT {dx} {dy} {'(Skipped)' if self._skip else ''}"
|
@@ -816,8 +860,11 @@ class ShxFont:
|
|
816
860
|
and the span.
|
817
861
|
:return:
|
818
862
|
"""
|
819
|
-
|
820
|
-
|
863
|
+
try:
|
864
|
+
radius = self.pop() * self._scale
|
865
|
+
sc = signed8(self.pop())
|
866
|
+
except ShxFontParseError:
|
867
|
+
return
|
821
868
|
s = (sc >> 4) & 0x7
|
822
869
|
c = sc & 0x7
|
823
870
|
if self._debug:
|
@@ -858,13 +905,15 @@ class ShxFont:
|
|
858
905
|
90° + (28/256 * 45°) = 95°
|
859
906
|
"""
|
860
907
|
octant = tau / 8.0
|
861
|
-
|
862
|
-
|
863
|
-
|
864
|
-
|
865
|
-
|
866
|
-
|
867
|
-
|
908
|
+
try:
|
909
|
+
start_offset = octant * self.pop() / 256.0
|
910
|
+
end_offset = octant * self.pop() / 256.0
|
911
|
+
radius = (256 * self.pop() + self.pop()) * self._scale
|
912
|
+
sc = signed8(self.pop())
|
913
|
+
s = (sc >> 4) & 0x7
|
914
|
+
c = sc & 0x7
|
915
|
+
except ShxFontParseError:
|
916
|
+
return
|
868
917
|
if self._debug:
|
869
918
|
print(
|
870
919
|
f"FRACTION_ARC {start_offset}, {end_offset}, {radius}, {s}, {c} {'(Skipped)' if self._skip else ''}"
|
@@ -903,10 +952,12 @@ class ShxFont:
|
|
903
952
|
|
904
953
|
:return:
|
905
954
|
"""
|
906
|
-
|
907
|
-
|
908
|
-
|
909
|
-
|
955
|
+
try:
|
956
|
+
dx = signed8(self.pop()) * self._scale
|
957
|
+
dy = signed8(self.pop()) * self._scale
|
958
|
+
h = signed8(self.pop())
|
959
|
+
except ShxFontParseError:
|
960
|
+
return
|
910
961
|
|
911
962
|
if self._debug:
|
912
963
|
print(f"BULGE_ARC {dx}, {dy}, {h} {'(Skipped)' if self._skip else ''}")
|
@@ -939,8 +990,12 @@ class ShxFont:
|
|
939
990
|
"""
|
940
991
|
h = 0
|
941
992
|
while True:
|
942
|
-
|
943
|
-
|
993
|
+
try:
|
994
|
+
dx = signed8(self.pop()) * self._scale
|
995
|
+
dy = signed8(self.pop()) * self._scale
|
996
|
+
except ShxFontParseError:
|
997
|
+
return
|
998
|
+
|
944
999
|
if self._debug:
|
945
1000
|
print(
|
946
1001
|
f"POLY_BULGE_ARC {dx}, {dy}, {h} {'(Skipped)' if self._skip else ''}"
|
@@ -949,7 +1004,10 @@ class ShxFont:
|
|
949
1004
|
if self._debug:
|
950
1005
|
print(f"POLY_BULGE_ARC (TERMINATED)")
|
951
1006
|
break
|
952
|
-
|
1007
|
+
try:
|
1008
|
+
h = signed8(self.pop())
|
1009
|
+
except ShxFontParseError:
|
1010
|
+
return
|
953
1011
|
if self._skip:
|
954
1012
|
continue
|
955
1013
|
r = abs(complex(dx, dy)) / 2
|