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.
Files changed (34) hide show
  1. {svg2gcode-3.0.1 → svg2gcode-3.0.3}/PKG-INFO +24 -7
  2. {svg2gcode-3.0.1 → svg2gcode-3.0.3}/README.md +23 -6
  3. {svg2gcode-3.0.1 → svg2gcode-3.0.3}/svg2gcode/__init__.py +1 -1
  4. {svg2gcode-3.0.1 → svg2gcode-3.0.3}/svg2gcode/__main__.py +3 -2
  5. {svg2gcode-3.0.1 → svg2gcode-3.0.3}/svg2gcode/svg_to_gcode/__init__.py +5 -3
  6. {svg2gcode-3.0.1 → svg2gcode-3.0.3}/svg2gcode/svg_to_gcode/compiler/_compiler.py +31 -11
  7. {svg2gcode-3.0.1 → svg2gcode-3.0.3}/svg2gcode/svg_to_gcode/css_color.py +10 -2
  8. {svg2gcode-3.0.1 → svg2gcode-3.0.3}/LICENSE +0 -0
  9. {svg2gcode-3.0.1 → svg2gcode-3.0.3}/pyproject.toml +0 -0
  10. {svg2gcode-3.0.1 → svg2gcode-3.0.3}/svg2gcode/svg_to_gcode/LICENSE +0 -0
  11. {svg2gcode-3.0.1 → svg2gcode-3.0.3}/svg2gcode/svg_to_gcode/compiler/__init__.py +0 -0
  12. {svg2gcode-3.0.1 → svg2gcode-3.0.3}/svg2gcode/svg_to_gcode/compiler/interfaces/__init__.py +0 -0
  13. {svg2gcode-3.0.1 → svg2gcode-3.0.3}/svg2gcode/svg_to_gcode/compiler/interfaces/_abstract_interface.py +0 -0
  14. {svg2gcode-3.0.1 → svg2gcode-3.0.3}/svg2gcode/svg_to_gcode/compiler/interfaces/_fan_controlled_gcode.py +0 -0
  15. {svg2gcode-3.0.1 → svg2gcode-3.0.3}/svg2gcode/svg_to_gcode/compiler/interfaces/_gcode.py +0 -0
  16. {svg2gcode-3.0.1 → svg2gcode-3.0.3}/svg2gcode/svg_to_gcode/formulas.py +0 -0
  17. {svg2gcode-3.0.1 → svg2gcode-3.0.3}/svg2gcode/svg_to_gcode/geometry/__init__.py +0 -0
  18. {svg2gcode-3.0.1 → svg2gcode-3.0.3}/svg2gcode/svg_to_gcode/geometry/_abstract_chain.py +0 -0
  19. {svg2gcode-3.0.1 → svg2gcode-3.0.3}/svg2gcode/svg_to_gcode/geometry/_abstract_curve.py +0 -0
  20. {svg2gcode-3.0.1 → svg2gcode-3.0.3}/svg2gcode/svg_to_gcode/geometry/_circular_arc.py +0 -0
  21. {svg2gcode-3.0.1 → svg2gcode-3.0.3}/svg2gcode/svg_to_gcode/geometry/_cubic_bazier.py +0 -0
  22. {svg2gcode-3.0.1 → svg2gcode-3.0.3}/svg2gcode/svg_to_gcode/geometry/_elliptical_arc.py +0 -0
  23. {svg2gcode-3.0.1 → svg2gcode-3.0.3}/svg2gcode/svg_to_gcode/geometry/_line.py +0 -0
  24. {svg2gcode-3.0.1 → svg2gcode-3.0.3}/svg2gcode/svg_to_gcode/geometry/_line_segment_chain.py +0 -0
  25. {svg2gcode-3.0.1 → svg2gcode-3.0.3}/svg2gcode/svg_to_gcode/geometry/_matrix.py +0 -0
  26. {svg2gcode-3.0.1 → svg2gcode-3.0.3}/svg2gcode/svg_to_gcode/geometry/_quadratic_bazier.py +0 -0
  27. {svg2gcode-3.0.1 → svg2gcode-3.0.3}/svg2gcode/svg_to_gcode/geometry/_raster_image.py +0 -0
  28. {svg2gcode-3.0.1 → svg2gcode-3.0.3}/svg2gcode/svg_to_gcode/geometry/_smooth_arc_chain.py +0 -0
  29. {svg2gcode-3.0.1 → svg2gcode-3.0.3}/svg2gcode/svg_to_gcode/geometry/_vector.py +0 -0
  30. {svg2gcode-3.0.1 → svg2gcode-3.0.3}/svg2gcode/svg_to_gcode/svg_parser/__init__.py +0 -0
  31. {svg2gcode-3.0.1 → svg2gcode-3.0.3}/svg2gcode/svg_to_gcode/svg_parser/_parser_methods.py +0 -0
  32. {svg2gcode-3.0.1 → svg2gcode-3.0.3}/svg2gcode/svg_to_gcode/svg_parser/_path.py +0 -0
  33. {svg2gcode-3.0.1 → svg2gcode-3.0.3}/svg2gcode/svg_to_gcode/svg_parser/_transformation.py +0 -0
  34. {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.1
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: runsvg2gcode [-h] [--showimage] [--selfcenter] [--pixelsize <default:0.1>] [--imagespeed <default:800>] [--cuttingspeed <default:1000>]
75
- [--imagepower <default:300>] [--poweroffset <default:0>] [--cuttingpower <default:850>] [--passes <default:1>] [--pass_depth <default:0>]
76
- [--rapidmove <default:10>] [--noise <default:0>] [--overscan <default:0>] [--showoverscan] [--constantburn] [--origin Xdelta Ydelta]
77
- [--scale Xfactor Yfactor] [--rotate <default:0>] [--splitfile] [--xmaxtravel <default:300>] [--ymaxtravel <default:400>] [--fan] [-V]
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 drawings/cutting
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: runsvg2gcode [-h] [--showimage] [--selfcenter] [--pixelsize <default:0.1>] [--imagespeed <default:800>] [--cuttingspeed <default:1000>]
61
- [--imagepower <default:300>] [--poweroffset <default:0>] [--cuttingpower <default:850>] [--passes <default:1>] [--pass_depth <default:0>]
62
- [--rapidmove <default:10>] [--noise <default:0>] [--overscan <default:0>] [--showoverscan] [--constantburn] [--origin Xdelta Ydelta]
63
- [--scale Xfactor Yfactor] [--rotate <default:0>] [--splitfile] [--xmaxtravel <default:300>] [--ymaxtravel <default:400>] [--fan] [-V]
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 drawings/cutting
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
  ```
@@ -1,4 +1,4 @@
1
1
  """
2
2
  svg2gcode: convert an SVG (Scalable Vector Graphic) image to gcode.
3
3
  """
4
- __version__ = "3.0.1"
4
+ __version__ = "3.0.3"
@@ -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 drawings/cutting")
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" # boolean return SVG path objects to <filename>.<gcext> and SVG image objects to <filename>_images.<gcext>
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
- logger.warn(f'No image found, skipping "{image_file_name}"')
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 curve
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:.+;',style_str)
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:.+;',style_str)
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
- # parse direct style curves
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
- style = self.parse_style_attribute(line_chain.get(0))
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['stroke'] is not None and style['stroke'] != "none":
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["saddlebrown"]["decimal"]
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