summaryrefslogtreecommitdiff
path: root/gerbonara/gerber
diff options
context:
space:
mode:
Diffstat (limited to 'gerbonara/gerber')
-rw-r--r--gerbonara/gerber/rs274x.py66
1 files changed, 30 insertions, 36 deletions
diff --git a/gerbonara/gerber/rs274x.py b/gerbonara/gerber/rs274x.py
index 2f41684..401047f 100644
--- a/gerbonara/gerber/rs274x.py
+++ b/gerbonara/gerber/rs274x.py
@@ -199,10 +199,10 @@ class GerberFile(CamFile):
for number, aperture in enumerate(self.apertures, start=10):
if isinstance(aperture, apertures.ApertureMacroInstance):
- macro_grb = aperture._rotated().macro.to_gerber() # use native unit to compare macros
- if macro_grb not in processed_macros:
- processed_macros.add(macro_grb)
- yield am_stmt(aperture._rotated().macro)
+ macro_def = am_stmt(aperture._rotated().macro)
+ if macro_def not in processed_macros:
+ processed_macros.add(macro_def)
+ yield macro_def
yield f'%ADD{number}{aperture.to_gerber(settings)}*%'
@@ -503,10 +503,6 @@ class GerberParser:
@classmethod
def _split_commands(kls, data):
- """
- Split the data into commands. Commands end with * (and also newline to help with some badly formatted files)
- """
-
start = 0
extended_command = False
lineno = 1
@@ -521,7 +517,9 @@ class GerberParser:
extended_command = False
else:
- extended_command = True
+ # Ignore % inside G04 comments
+ if not data[start:pos].startswith('G04'):
+ extended_command = True
start = pos + 1
continue
@@ -581,12 +579,8 @@ class GerberParser:
elif match['interpolation'] == 'G75':
self.multi_quadrant_mode = False
- if match['interpolation'] in ('G74', 'G75'):
- if match[0] == match['interpolation']:
- return # nothing else to do
-
- else:
- raise SyntaxError('G74/G75 combined with coord')
+ if match['interpolation'] in ('G74', 'G75') and (match['x'] or match['y'] or match['i'] or match['j']):
+ raise SyntaxError('G74/G75 combined with coord')
x = self.file_settings.parse_gerber_value(match['x'])
y = self.file_settings.parse_gerber_value(match['y'])
@@ -595,10 +589,10 @@ class GerberParser:
if not (op := match['operation']):
if self.last_operation == 'D01':
- warnings.warn('Coordinate statement without explicit operation code. This is forbidden by spec.',
- SyntaxWarning)
+ warnings.warn('Coordinate statement without explicit operation code. This is forbidden by spec.', SyntaxWarning)
op = 'D01'
- else:
+
+ elif match['x'] or match['y'] or match['i'] or match['j']:
raise SyntaxError('Ambiguous coordinate statement. Coordinate statement does not have an operation '\
'mode and the last operation statement was not D01.')
@@ -618,25 +612,25 @@ class GerberParser:
else:
self.current_region.append(self.graphics_state.interpolate(x, y, i, j, aperture=False))
+ elif op in ('D2', 'D02'):
+ self.graphics_state.update_point(x, y)
+ if self.current_region:
+ # Start a new region for every outline. As gerber has no concept of fill rules or winding numbers,
+ # it does not make a graphical difference, and it makes the implementation slightly easier.
+ self.target.objects.append(self.current_region)
+ self.current_region = go.Region(
+ polarity_dark=self.graphics_state.polarity_dark,
+ unit=self.file_settings.unit)
+
+ elif op in ('D3', 'D03'):
+ if self.current_region is None:
+ self.target.objects.append(self.graphics_state.flash(x, y))
+ else:
+ raise SyntaxError('DO3 flash statement inside region')
+
else:
- if i is not None or j is not None:
- raise SyntaxError("i/j coordinates given for D02/D03 operation (which doesn't take i/j)")
-
- if op in ('D2', 'D02'):
- self.graphics_state.update_point(x, y)
- if self.current_region:
- # Start a new region for every outline. As gerber has no concept of fill rules or winding numbers,
- # it does not make a graphical difference, and it makes the implementation slightly easier.
- self.target.objects.append(self.current_region)
- self.current_region = go.Region(
- polarity_dark=self.graphics_state.polarity_dark,
- unit=self.file_settings.unit)
-
- else: # D03
- if self.current_region is None:
- self.target.objects.append(self.graphics_state.flash(x, y))
- else:
- raise SyntaxError('DO3 flash statement inside region')
+ # Do nothing if there is no explicit D code.
+ pass
def _parse_aperture(self, match):
number = int(match['number'])