svg2gcode 3.0.1__tar.gz → 3.0.3__tar.gz
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.
- {svg2gcode-3.0.1 → svg2gcode-3.0.3}/PKG-INFO +24 -7
- {svg2gcode-3.0.1 → svg2gcode-3.0.3}/README.md +23 -6
- {svg2gcode-3.0.1 → svg2gcode-3.0.3}/svg2gcode/__init__.py +1 -1
- {svg2gcode-3.0.1 → svg2gcode-3.0.3}/svg2gcode/__main__.py +3 -2
- {svg2gcode-3.0.1 → svg2gcode-3.0.3}/svg2gcode/svg_to_gcode/__init__.py +5 -3
- {svg2gcode-3.0.1 → svg2gcode-3.0.3}/svg2gcode/svg_to_gcode/compiler/_compiler.py +31 -11
- {svg2gcode-3.0.1 → svg2gcode-3.0.3}/svg2gcode/svg_to_gcode/css_color.py +10 -2
- {svg2gcode-3.0.1 → svg2gcode-3.0.3}/LICENSE +0 -0
- {svg2gcode-3.0.1 → svg2gcode-3.0.3}/pyproject.toml +0 -0
- {svg2gcode-3.0.1 → svg2gcode-3.0.3}/svg2gcode/svg_to_gcode/LICENSE +0 -0
- {svg2gcode-3.0.1 → svg2gcode-3.0.3}/svg2gcode/svg_to_gcode/compiler/__init__.py +0 -0
- {svg2gcode-3.0.1 → svg2gcode-3.0.3}/svg2gcode/svg_to_gcode/compiler/interfaces/__init__.py +0 -0
- {svg2gcode-3.0.1 → svg2gcode-3.0.3}/svg2gcode/svg_to_gcode/compiler/interfaces/_abstract_interface.py +0 -0
- {svg2gcode-3.0.1 → svg2gcode-3.0.3}/svg2gcode/svg_to_gcode/compiler/interfaces/_fan_controlled_gcode.py +0 -0
- {svg2gcode-3.0.1 → svg2gcode-3.0.3}/svg2gcode/svg_to_gcode/compiler/interfaces/_gcode.py +0 -0
- {svg2gcode-3.0.1 → svg2gcode-3.0.3}/svg2gcode/svg_to_gcode/formulas.py +0 -0
- {svg2gcode-3.0.1 → svg2gcode-3.0.3}/svg2gcode/svg_to_gcode/geometry/__init__.py +0 -0
- {svg2gcode-3.0.1 → svg2gcode-3.0.3}/svg2gcode/svg_to_gcode/geometry/_abstract_chain.py +0 -0
- {svg2gcode-3.0.1 → svg2gcode-3.0.3}/svg2gcode/svg_to_gcode/geometry/_abstract_curve.py +0 -0
- {svg2gcode-3.0.1 → svg2gcode-3.0.3}/svg2gcode/svg_to_gcode/geometry/_circular_arc.py +0 -0
- {svg2gcode-3.0.1 → svg2gcode-3.0.3}/svg2gcode/svg_to_gcode/geometry/_cubic_bazier.py +0 -0
- {svg2gcode-3.0.1 → svg2gcode-3.0.3}/svg2gcode/svg_to_gcode/geometry/_elliptical_arc.py +0 -0
- {svg2gcode-3.0.1 → svg2gcode-3.0.3}/svg2gcode/svg_to_gcode/geometry/_line.py +0 -0
- {svg2gcode-3.0.1 → svg2gcode-3.0.3}/svg2gcode/svg_to_gcode/geometry/_line_segment_chain.py +0 -0
- {svg2gcode-3.0.1 → svg2gcode-3.0.3}/svg2gcode/svg_to_gcode/geometry/_matrix.py +0 -0
- {svg2gcode-3.0.1 → svg2gcode-3.0.3}/svg2gcode/svg_to_gcode/geometry/_quadratic_bazier.py +0 -0
- {svg2gcode-3.0.1 → svg2gcode-3.0.3}/svg2gcode/svg_to_gcode/geometry/_raster_image.py +0 -0
- {svg2gcode-3.0.1 → svg2gcode-3.0.3}/svg2gcode/svg_to_gcode/geometry/_smooth_arc_chain.py +0 -0
- {svg2gcode-3.0.1 → svg2gcode-3.0.3}/svg2gcode/svg_to_gcode/geometry/_vector.py +0 -0
- {svg2gcode-3.0.1 → svg2gcode-3.0.3}/svg2gcode/svg_to_gcode/svg_parser/__init__.py +0 -0
- {svg2gcode-3.0.1 → svg2gcode-3.0.3}/svg2gcode/svg_to_gcode/svg_parser/_parser_methods.py +0 -0
- {svg2gcode-3.0.1 → svg2gcode-3.0.3}/svg2gcode/svg_to_gcode/svg_parser/_path.py +0 -0
- {svg2gcode-3.0.1 → svg2gcode-3.0.3}/svg2gcode/svg_to_gcode/svg_parser/_transformation.py +0 -0
- {svg2gcode-3.0.1 → svg2gcode-3.0.3}/svg2gcode/svg_to_gcode/svg_parser/debug_methods.py +0 -0
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.1
|
|
2
2
|
Name: svg2gcode
|
|
3
|
-
Version: 3.0.
|
|
3
|
+
Version: 3.0.3
|
|
4
4
|
Summary: svg2gcode: convert an SVG (Scalable Vector Graphic) image to gcode.
|
|
5
5
|
Keywords: scalable vector graphics,svg,image,laser cutter,laser engraving
|
|
6
6
|
Author-email: Johannes Noordanus <mailjohannes.mailnoordanus@gmail.com>
|
|
@@ -41,6 +41,14 @@ See options ```--speedmoves``` and ```--noise``` for example.
|
|
|
41
41
|
Version 3.0.0 and higher have support for 'stroke' (color) and 'stroke-width' attributes, this means that cutting a path works a bit different now.
|
|
42
42
|
When the *stroke* attribute of a *path* is nonexistent or set to none, the path will be laser burned with the value set by option *--cuttingpower*.
|
|
43
43
|
|
|
44
|
+
Also, *svg2gcode* option ```--pathcut``` can be used to override all stroke attributes and force cutting of all *paths* of the SVG.
|
|
45
|
+
But, see the examples below.
|
|
46
|
+
|
|
47
|
+
Please consider supporting me, so I can make this application better and add new functionality to it: <http://paypal.me/johannesnoordanus/5,00>
|
|
48
|
+
|
|
49
|
+
My next update will be a major one, I'll add support for the *fill* attribute of SVG objects.
|
|
50
|
+
|
|
51
|
+
|
|
44
52
|
To summarize:
|
|
45
53
|
|
|
46
54
|
Optimized gcode
|
|
@@ -70,11 +78,11 @@ also, program *image2gcode* has similar capabilities but handles raster images f
|
|
|
70
78
|
<sup>(*)</sup> Note that an upgraded and corrected version of this library is included.
|
|
71
79
|
### Usage:
|
|
72
80
|
```
|
|
73
|
-
svg2gcode --help
|
|
74
|
-
usage:
|
|
75
|
-
[--
|
|
76
|
-
[--
|
|
77
|
-
[--
|
|
81
|
+
> svg2gcode --help
|
|
82
|
+
usage: svg2gcode [-h] [--showimage] [--selfcenter] [--pixelsize <default:0.1>] [--imagespeed <default:800>] [--cuttingspeed <default:1000>] [--imagepower <default:300>]
|
|
83
|
+
[--poweroffset <default:0>] [--cuttingpower <default:850>] [--passes <default:1>] [--pass_depth <default:0>] [--rapidmove <default:10>] [--noise <default:0>]
|
|
84
|
+
[--overscan <default:0>] [--showoverscan] [--constantburn] [--origin delta-x delta-y] [--scale factor-x factor-y] [--rotate <default:0>] [--splitfile] [--pathcut]
|
|
85
|
+
[--xmaxtravel <default:300>] [--ymaxtravel <default:400>] [--fan] [-V]
|
|
78
86
|
svg gcode
|
|
79
87
|
|
|
80
88
|
Convert svg to gcode for GRBL v1.1 compatible diode laser engravers.
|
|
@@ -98,7 +106,7 @@ options:
|
|
|
98
106
|
--poweroffset <default:0>
|
|
99
107
|
pixel intensity to laser power: shift power range [0-imagepower]
|
|
100
108
|
--cuttingpower <default:850>
|
|
101
|
-
sets laser power of line
|
|
109
|
+
sets laser power of line (path) cutting
|
|
102
110
|
--passes <default:1> Number of passes (iterations) for line drawings, only active when pass_depth is set
|
|
103
111
|
--pass_depth <default:0>
|
|
104
112
|
cutting depth in mm for one pass, only active for passes > 1
|
|
@@ -115,6 +123,7 @@ options:
|
|
|
115
123
|
scale svg with (factor-x,factor-y) (default not set)
|
|
116
124
|
--rotate <default:0> number of degrees to rotate
|
|
117
125
|
--splitfile split gcode output of SVG path and image objects
|
|
126
|
+
--pathcut alway cut SVG path objects! (use laser power set with option --cuttingpower)
|
|
118
127
|
--xmaxtravel <default:300>
|
|
119
128
|
machine x-axis lengh in mm
|
|
120
129
|
--ymaxtravel <default:400>
|
|
@@ -214,6 +223,14 @@ Change the *style* attribute line - within file *line_hoek.svg* - to the followi
|
|
|
214
223
|
```
|
|
215
224
|
style="fill:none;stroke:none;stroke-width:.1"
|
|
216
225
|
```
|
|
226
|
+
or add 'gcode-pathcut' to the style string:
|
|
227
|
+
```
|
|
228
|
+
style="fill:none;stroke:red;stroke-width:.1;gcode-pathcut:true"
|
|
229
|
+
```
|
|
230
|
+
(Note that this makes it possible to selectively cut path objects within the SVG.)
|
|
231
|
+
|
|
232
|
+
or add *svg2gcode* option *--pathcut* to override all path stroke attributes within the SVG document
|
|
233
|
+
|
|
217
234
|
Run *svg2gcode* (with same options) again.
|
|
218
235
|
Now the gcode after conversion will look like this:
|
|
219
236
|
```
|
|
@@ -27,6 +27,14 @@ See options ```--speedmoves``` and ```--noise``` for example.
|
|
|
27
27
|
Version 3.0.0 and higher have support for 'stroke' (color) and 'stroke-width' attributes, this means that cutting a path works a bit different now.
|
|
28
28
|
When the *stroke* attribute of a *path* is nonexistent or set to none, the path will be laser burned with the value set by option *--cuttingpower*.
|
|
29
29
|
|
|
30
|
+
Also, *svg2gcode* option ```--pathcut``` can be used to override all stroke attributes and force cutting of all *paths* of the SVG.
|
|
31
|
+
But, see the examples below.
|
|
32
|
+
|
|
33
|
+
Please consider supporting me, so I can make this application better and add new functionality to it: <http://paypal.me/johannesnoordanus/5,00>
|
|
34
|
+
|
|
35
|
+
My next update will be a major one, I'll add support for the *fill* attribute of SVG objects.
|
|
36
|
+
|
|
37
|
+
|
|
30
38
|
To summarize:
|
|
31
39
|
|
|
32
40
|
Optimized gcode
|
|
@@ -56,11 +64,11 @@ also, program *image2gcode* has similar capabilities but handles raster images f
|
|
|
56
64
|
<sup>(*)</sup> Note that an upgraded and corrected version of this library is included.
|
|
57
65
|
### Usage:
|
|
58
66
|
```
|
|
59
|
-
svg2gcode --help
|
|
60
|
-
usage:
|
|
61
|
-
[--
|
|
62
|
-
[--
|
|
63
|
-
[--
|
|
67
|
+
> svg2gcode --help
|
|
68
|
+
usage: svg2gcode [-h] [--showimage] [--selfcenter] [--pixelsize <default:0.1>] [--imagespeed <default:800>] [--cuttingspeed <default:1000>] [--imagepower <default:300>]
|
|
69
|
+
[--poweroffset <default:0>] [--cuttingpower <default:850>] [--passes <default:1>] [--pass_depth <default:0>] [--rapidmove <default:10>] [--noise <default:0>]
|
|
70
|
+
[--overscan <default:0>] [--showoverscan] [--constantburn] [--origin delta-x delta-y] [--scale factor-x factor-y] [--rotate <default:0>] [--splitfile] [--pathcut]
|
|
71
|
+
[--xmaxtravel <default:300>] [--ymaxtravel <default:400>] [--fan] [-V]
|
|
64
72
|
svg gcode
|
|
65
73
|
|
|
66
74
|
Convert svg to gcode for GRBL v1.1 compatible diode laser engravers.
|
|
@@ -84,7 +92,7 @@ options:
|
|
|
84
92
|
--poweroffset <default:0>
|
|
85
93
|
pixel intensity to laser power: shift power range [0-imagepower]
|
|
86
94
|
--cuttingpower <default:850>
|
|
87
|
-
sets laser power of line
|
|
95
|
+
sets laser power of line (path) cutting
|
|
88
96
|
--passes <default:1> Number of passes (iterations) for line drawings, only active when pass_depth is set
|
|
89
97
|
--pass_depth <default:0>
|
|
90
98
|
cutting depth in mm for one pass, only active for passes > 1
|
|
@@ -101,6 +109,7 @@ options:
|
|
|
101
109
|
scale svg with (factor-x,factor-y) (default not set)
|
|
102
110
|
--rotate <default:0> number of degrees to rotate
|
|
103
111
|
--splitfile split gcode output of SVG path and image objects
|
|
112
|
+
--pathcut alway cut SVG path objects! (use laser power set with option --cuttingpower)
|
|
104
113
|
--xmaxtravel <default:300>
|
|
105
114
|
machine x-axis lengh in mm
|
|
106
115
|
--ymaxtravel <default:400>
|
|
@@ -200,6 +209,14 @@ Change the *style* attribute line - within file *line_hoek.svg* - to the followi
|
|
|
200
209
|
```
|
|
201
210
|
style="fill:none;stroke:none;stroke-width:.1"
|
|
202
211
|
```
|
|
212
|
+
or add 'gcode-pathcut' to the style string:
|
|
213
|
+
```
|
|
214
|
+
style="fill:none;stroke:red;stroke-width:.1;gcode-pathcut:true"
|
|
215
|
+
```
|
|
216
|
+
(Note that this makes it possible to selectively cut path objects within the SVG.)
|
|
217
|
+
|
|
218
|
+
or add *svg2gcode* option *--pathcut* to override all path stroke attributes within the SVG document
|
|
219
|
+
|
|
203
220
|
Run *svg2gcode* (with same options) again.
|
|
204
221
|
Now the gcode after conversion will look like this:
|
|
205
222
|
```
|
|
@@ -36,7 +36,7 @@ def svg2gcode(args) -> int:
|
|
|
36
36
|
return Compiler(interfaces.Gcode, params={'laser_power':args.cuttingpower,'movement_speed':args.cuttingspeed, 'pixel_size':args.pixelsize,
|
|
37
37
|
'maximum_image_laser_power':args.imagepower, 'image_movement_speed':args.imagespeed, 'fan':args.fan,'rapid_move':args.rapidmove,
|
|
38
38
|
'showimage':args.showimage, 'x_axis_maximum_travel':args.xmaxtravel,'y_axis_maximum_travel':args.ymaxtravel, 'image_noise':args.noise,
|
|
39
|
-
'pass_depth':args.pass_depth, 'laser_mode':"constant" if args.constantburn else "dynamic", 'splitfile':args.splitfile,
|
|
39
|
+
'pass_depth':args.pass_depth, 'laser_mode':"constant" if args.constantburn else "dynamic", 'splitfile':args.splitfile, 'pathcut':args.pathcut,
|
|
40
40
|
'image_poweroffset':args.poweroffset, 'image_overscan':args.overscan, 'image_showoverscan':args.showoverscan})
|
|
41
41
|
|
|
42
42
|
compiler = init_compiler(args)
|
|
@@ -117,7 +117,7 @@ def main() -> int:
|
|
|
117
117
|
parser.add_argument('--poweroffset', default=cfg["poweroffset_default"], metavar="<default:" +str(cfg["poweroffset_default"])+ ">",
|
|
118
118
|
type=int, help="pixel intensity to laser power: shift power range [0-imagepower]")
|
|
119
119
|
parser.add_argument('--cuttingpower', default=cfg["cuttingpower_default"], metavar="<default:" +str(cfg["cuttingpower_default"])+ ">",
|
|
120
|
-
type=int, help="sets laser power of line
|
|
120
|
+
type=int, help="sets laser power of line (path) cutting")
|
|
121
121
|
parser.add_argument('--passes', default=cfg["passes_default"], metavar="<default:" +str(cfg["passes_default"])+ ">",
|
|
122
122
|
type=int, help="Number of passes (iterations) for line drawings, only active when pass_depth is set")
|
|
123
123
|
parser.add_argument('--pass_depth', default=cfg["pass_depth_default"], metavar="<default:" + str(cfg["pass_depth_default"])+">",
|
|
@@ -137,6 +137,7 @@ def main() -> int:
|
|
|
137
137
|
parser.add_argument('--rotate', default=cfg["rotate_default"], metavar="<default:" +str(cfg["rotate_default"])+ ">",
|
|
138
138
|
type=int, help="number of degrees to rotate")
|
|
139
139
|
parser.add_argument('--splitfile', action='store_true', default=False, help='split gcode output of SVG path and image objects' )
|
|
140
|
+
parser.add_argument('--pathcut', action='store_true', default=False, help='alway cut SVG path objects! (use laser power set with option --cuttingpower)' )
|
|
140
141
|
parser.add_argument('--xmaxtravel', default=cfg["xmaxtravel_default"], metavar="<default:" +str(cfg["xmaxtravel_default"])+ ">",
|
|
141
142
|
type=int, help="machine x-axis lengh in mm")
|
|
142
143
|
parser.add_argument('--ymaxtravel', default=cfg["ymaxtravel_default"], metavar="<default:" +str(cfg["ymaxtravel_default"])+ ">",
|
|
@@ -38,7 +38,8 @@ SETTING = {
|
|
|
38
38
|
# more than 'n'mm
|
|
39
39
|
"pixel_size", # float sets image pixel size (in mm)
|
|
40
40
|
"showimage", # boolean show image used for conversion to gcode
|
|
41
|
-
"splitfile"
|
|
41
|
+
"splitfile", # boolean return SVG path objects to <filename>.<gcext> and SVG image objects to <filename>_images.<gcext>
|
|
42
|
+
"pathcut" # boolean always cut SVG path objects! use laser_power setting
|
|
42
43
|
}
|
|
43
44
|
|
|
44
45
|
# Set defaults 'minimum_laser_power', 'pass_depth', 'dwell_time', 'laser_power', 'laser_mode', 'unit', 'distance_mode'
|
|
@@ -70,7 +71,8 @@ DEFAULT_SETTING = {
|
|
|
70
71
|
"rapid_move": 10, # default set to true, for images do a rapid move when skipping more than 10mm
|
|
71
72
|
"pixel_size": 0.1, # laser kerf is mostly < 0.1mm
|
|
72
73
|
"showimage": False, # default image is not shown
|
|
73
|
-
"splitfile": False # SVG path and image objects are emitted to one file: <filename>.<gcext>
|
|
74
|
+
"splitfile": False, # SVG path and image objects are emitted to one file: <filename>.<gcext>
|
|
75
|
+
"pathcut": False # always cut SVG path objects! use laser_power setting
|
|
74
76
|
}
|
|
75
77
|
|
|
76
78
|
def check_setting(setting: dict[str,Any] =None) -> bool:
|
|
@@ -112,7 +114,7 @@ def check_setting(setting: dict[str,Any] =None) -> bool:
|
|
|
112
114
|
raise ValueError(f"Unknown '{key}' value '{setting[key]}'. Please specify one of the following: {UNITS}")
|
|
113
115
|
if key == "distance_mode" and setting[key] not in DISTANCEMODE:
|
|
114
116
|
raise ValueError(f"Unknown '{key}' value '{setting[key]}'. Please specify one of the following: {DISTANCEMODE}")
|
|
115
|
-
if key in {"fan","showimage","splitfile","image_showoverscan"} and setting[key] not in {True,False}:
|
|
117
|
+
if key in {"fan","showimage","splitfile","pathcut","image_showoverscan"} and setting[key] not in {True,False}:
|
|
116
118
|
raise ValueError(f"Unknown '{key}' value '{setting[key]}'. Please specify one of the following: {{True,False}}")
|
|
117
119
|
if key == "pixel_size" and setting[key] and (not isinstance(setting[key],(float)) or setting[key] <= 0):
|
|
118
120
|
raise TypeError(f"'{key}' is of type '{type(setting[key])}' but should be of type {type(1.0)} and have a value > 0.0")
|
|
@@ -193,7 +193,10 @@ class Compiler:
|
|
|
193
193
|
|
|
194
194
|
image_file_name = file_name.rsplit('.',1)[0] + "_images." + file_name.rsplit('.',1)[1]
|
|
195
195
|
if len(self.gcode) == 0:
|
|
196
|
-
|
|
196
|
+
if self.settings["splitfile"]:
|
|
197
|
+
logger.warn(f"No image found, skipping '{image_file_name}'")
|
|
198
|
+
else:
|
|
199
|
+
logger.warn(f"No image found in file '{svg_file_name}'")
|
|
197
200
|
else:
|
|
198
201
|
if self.settings["splitfile"]:
|
|
199
202
|
# emit image objects to <filename>_images.<gcext>
|
|
@@ -474,16 +477,16 @@ class Compiler:
|
|
|
474
477
|
for example "fill:#F4CF84;fill-rule:evenodd;stroke:#D07735;"
|
|
475
478
|
"""
|
|
476
479
|
|
|
477
|
-
style = {'fill' : None, 'fill-rule': None, 'stroke': None, 'stroke-width': None}
|
|
480
|
+
style = {'fill' : None, 'fill-rule': None, 'stroke': None, 'stroke-width': None, 'pathcut': None}
|
|
478
481
|
|
|
479
|
-
# parse style
|
|
482
|
+
# parse style attribute
|
|
480
483
|
|
|
481
484
|
if curve.path_attrib and 'style' in curve.path_attrib:
|
|
482
485
|
style_str = curve.path_attrib['style']
|
|
483
486
|
|
|
484
487
|
# parse fill
|
|
485
488
|
if 'fill' in style_str:
|
|
486
|
-
fill = re.search('fill
|
|
489
|
+
fill = re.search('fill:[^;]+;',style_str)
|
|
487
490
|
if fill:
|
|
488
491
|
style['fill'] = fill.group(0)[5:-1]
|
|
489
492
|
# parse fill-rule
|
|
@@ -493,7 +496,7 @@ class Compiler:
|
|
|
493
496
|
style['fill-rule'] = re.search('(evenodd|nonzero)', fill_rule.group(0)).group(0)
|
|
494
497
|
# parse stroke
|
|
495
498
|
if 'stroke' in style_str:
|
|
496
|
-
stroke = re.search('stroke
|
|
499
|
+
stroke = re.search('stroke:[^;]+;',style_str)
|
|
497
500
|
if stroke:
|
|
498
501
|
style['stroke'] = stroke.group(0)[7:-1]
|
|
499
502
|
# parse stroke-width
|
|
@@ -502,16 +505,30 @@ class Compiler:
|
|
|
502
505
|
if stroke_width:
|
|
503
506
|
style['stroke-width'] = re.search('(\d*\.)?\d+', stroke_width.group(0)).group(0)
|
|
504
507
|
|
|
505
|
-
|
|
508
|
+
# parse pathcut
|
|
509
|
+
if 'gcode-pathcut' in style_str:
|
|
510
|
+
pathcut = re.search('gcode-pathcut:(true|false)',style_str)
|
|
511
|
+
if pathcut:
|
|
512
|
+
style['pathcut'] = re.search('(true|false)', pathcut.group(0)).group(0)
|
|
513
|
+
|
|
514
|
+
# parse other attributes
|
|
506
515
|
|
|
507
|
-
# parse fill
|
|
516
|
+
# parse fill attribute
|
|
508
517
|
if 'fill' in curve.path_attrib:
|
|
509
518
|
style['fill'] = curve.path_attrib['fill']
|
|
510
519
|
if 'fill-rule' in curve.path_attrib:
|
|
511
520
|
style['fill-rule'] = curve.path_attrib['fill-rule']
|
|
521
|
+
# parse stroke attribute
|
|
522
|
+
if 'stroke' in curve.path_attrib:
|
|
523
|
+
style['stroke'] = curve.path_attrib['stroke']
|
|
524
|
+
# parse stroke-width attribute
|
|
512
525
|
if 'stroke-width' in curve.path_attrib:
|
|
513
526
|
style['stroke-width'] = curve.path_attrib['stroke-width']
|
|
514
527
|
|
|
528
|
+
# parse gcode_pathcut attribute
|
|
529
|
+
if 'gcode_pathcut' in curve.path_attrib:
|
|
530
|
+
style['pathcut'] = curve.path_attrib['gcode_pathcut']
|
|
531
|
+
|
|
515
532
|
return style
|
|
516
533
|
|
|
517
534
|
def append_curves(self, curves: list[Curve]):
|
|
@@ -563,12 +580,15 @@ class Compiler:
|
|
|
563
580
|
pixel_size = float(self.settings["pixel_size"])
|
|
564
581
|
# default stroke width is one line (thickness)
|
|
565
582
|
stroke_width = pixel_size
|
|
566
|
-
stroke_color = ""
|
|
567
|
-
width = 0
|
|
568
583
|
|
|
569
|
-
|
|
584
|
+
first_line_of_chain = line_chain.get(0)
|
|
585
|
+
|
|
586
|
+
width = 0
|
|
587
|
+
stroke_color = ""
|
|
588
|
+
style = self.parse_style_attribute(first_line_of_chain)
|
|
570
589
|
if style:
|
|
571
|
-
if style['
|
|
590
|
+
if not (style['pathcut'] == 'true' or self.settings["pathcut"]) \
|
|
591
|
+
and style['stroke'] is not None and style['stroke'] != "none":
|
|
572
592
|
stroke_color = style['stroke']
|
|
573
593
|
if style['stroke-width'] is not None and style['stroke-width'] != "none":
|
|
574
594
|
stroke_width = float(style['stroke-width'])
|
|
@@ -3,10 +3,14 @@
|
|
|
3
3
|
currently only partially implemented
|
|
4
4
|
(definition from https://www.w3.org/TR/css-color-3/)
|
|
5
5
|
"""
|
|
6
|
-
|
|
6
|
+
import logging
|
|
7
7
|
import math
|
|
8
8
|
import re
|
|
9
9
|
|
|
10
|
+
logging.basicConfig(format="[%(levelname)s] %(message)s")
|
|
11
|
+
logger = logging.getLogger(__name__)
|
|
12
|
+
logger.setLevel(logging.INFO)
|
|
13
|
+
|
|
10
14
|
css_color_keywords = {
|
|
11
15
|
"aliceblue": { "hex": "#F0F8FF", "decimal": [240,248,255] },
|
|
12
16
|
"antiquewhite": { "hex": "#FAEBD7", "decimal": [250,235,215] },
|
|
@@ -199,7 +203,7 @@ def parse_css_color(color: str) -> [int,int,int]:
|
|
|
199
203
|
rgbcolor = 0
|
|
200
204
|
|
|
201
205
|
if color in css_color_keywords:
|
|
202
|
-
rgbcolor = css_color_keywords[
|
|
206
|
+
rgbcolor = css_color_keywords[color]["decimal"]
|
|
203
207
|
else:
|
|
204
208
|
hexcolor = re.search('#[A-Fa-f0-9]+', color)
|
|
205
209
|
if hexcolor:
|
|
@@ -247,6 +251,10 @@ def parse_css_color(color: str) -> [int,int,int]:
|
|
|
247
251
|
rgbcolor = hsl2rgb(h, s, l)
|
|
248
252
|
rgbcolor = [int(rgbcolor[0] * 255 * a), int(rgbcolor[1] * 255 * a), int(rgbcolor[2] * 255 * a)]
|
|
249
253
|
|
|
254
|
+
if not rgbcolor:
|
|
255
|
+
logger.warn(f"Not a valid css color: '{color}', color set to 'black'!")
|
|
256
|
+
rgbcolor = css_color_keywords['black']["decimal"]
|
|
257
|
+
|
|
250
258
|
return rgbcolor
|
|
251
259
|
|
|
252
260
|
def rgb24tobw24(rgb24: int) -> int:
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|