summaryrefslogtreecommitdiff
path: root/gerbonara/gerber
diff options
context:
space:
mode:
Diffstat (limited to 'gerbonara/gerber')
-rw-r--r--gerbonara/gerber/rs274x.py21
-rw-r--r--gerbonara/gerber/tests/resources/open_outline_altium.gbr55
-rw-r--r--gerbonara/gerber/utils.py3
3 files changed, 71 insertions, 8 deletions
diff --git a/gerbonara/gerber/rs274x.py b/gerbonara/gerber/rs274x.py
index 6d373ba..2f41684 100644
--- a/gerbonara/gerber/rs274x.py
+++ b/gerbonara/gerber/rs274x.py
@@ -35,7 +35,7 @@ import textwrap
import dataclasses
from .cam import CamFile, FileSettings
-from .utils import sq_distance, rotate_point, MM, Inch, units, InterpMode
+from .utils import sq_distance, rotate_point, MM, Inch, units, InterpMode, UnknownStatementWarning
from .aperture_macros.parse import ApertureMacro, GenericMacros
from . import graphic_primitives as gp
from . import graphic_objects as go
@@ -171,6 +171,7 @@ class GerberFile(CamFile):
return obj
def generate_statements(self, settings, drop_comments=True):
+ yield 'G04 Gerber file generated by Gerbonara*'
yield '%MOMM*%' if (settings.unit == 'mm') else '%MOIN*%'
zeros = 'T' if settings.zeros == 'trailing' else 'L' # default to leading if "None" is specified
@@ -182,9 +183,9 @@ class GerberFile(CamFile):
yield '%LPD*%'
if not drop_comments:
- yield 'G04 File processed by Gerbonara. Original comments:'
+ yield 'G04 Comments from original gerber file:*'
for cmt in self.comments:
- yield f'G04{cmt}'
+ yield f'G04{cmt}*'
# Always emit gerbonara's generic, rotation-capable aperture macro replacements for the standard C/R/O/P shapes.
# Unconditionally emitting these here is easier than first trying to figure out if we need them later,
@@ -453,7 +454,7 @@ class GerberParser:
'region_end': r'G37$',
'coord': fr"(?P<interpolation>G0?[123]|G74|G75)?(X(?P<x>{NUMBER}))?(Y(?P<y>{NUMBER}))?" \
fr"(I(?P<i>{NUMBER}))?(J(?P<j>{NUMBER}))?" \
- fr"(?P<operation>D0?[123])$",
+ fr"(?P<operation>D0?[123])?$",
'aperture': r"(G54|G55)?D(?P<number>\d+)",
'comment': r"G0?4(?P<comment>[^*]*)",
# Allegro combines format spec and unit into one long illegal extended command.
@@ -549,7 +550,7 @@ class GerberParser:
if (match := le_regex.match(line)):
#print(f' match: {name} / {match}')
try:
- getattr(self, f'_parse_{name}')(match.groupdict())
+ getattr(self, f'_parse_{name}')(match)
except:
print(f'Line {lineno}: {line}')
print(f' match: {name} / {match}')
@@ -558,7 +559,7 @@ class GerberParser:
break
else:
- warnings.warn(f'Unknown statement found: "{line}", ignoring.', SyntaxWarning)
+ warnings.warn(f'Unknown statement found: "{line}", ignoring.', UnknownStatementWarning)
self.target.comments.append(f'Unknown statement found: "{line}", ignoring.')
self.target.apertures = list(self.aperture_map.values())
@@ -580,8 +581,12 @@ class GerberParser:
elif match['interpolation'] == 'G75':
self.multi_quadrant_mode = False
- if match['interpolation'] in ('G74', 'G75') and match[0] != match['interpolation']:
- raise SyntaxError('G74/G75 combined with coord')
+ if match['interpolation'] in ('G74', 'G75'):
+ if match[0] == match['interpolation']:
+ return # nothing else to do
+
+ else:
+ 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'])
diff --git a/gerbonara/gerber/tests/resources/open_outline_altium.gbr b/gerbonara/gerber/tests/resources/open_outline_altium.gbr
new file mode 100644
index 0000000..dc5a1d6
--- /dev/null
+++ b/gerbonara/gerber/tests/resources/open_outline_altium.gbr
@@ -0,0 +1,55 @@
+G04 From https://github.com/tracespace/tracespace/issues/365
+G04 Generated by Cuprum (2.1.4) at 2021-06-09T12:46:32+02:00*
+%FSLAX66Y66*%
+%MOMM*%
+%TF.FileFunction,FabricationDrawing*%
+%TF.SameCoordinates,1C0E9664-7553-46ED-9293-C2E7D2B0B53A*%
+%TF.CreationDate,2021-06-09T12:46:32+02:00*%
+%TF.GenerationSoftware,Wortum,Cuprum,2.1.4*%
+%ADD10C,0.1*%
+%ADD11C,0.254*%
+G75*
+D10*
+X28008000Y22481000D02*
+G03X26989000Y23500000I-1019000D01*
+X24451000Y36745000D02*
+X23451000Y37745000I-1000000D01*
+X26989000Y0D02*
+X28008000Y1019000J1019000D01*
+X8000Y1034000D02*
+X1042000Y0I1034000D01*
+Y23500000D02*
+X8000Y22466000J-1034000D01*
+X17090000Y37745000D02*
+X16090000Y36745000J-1000000D01*
+X16078000Y36618000D02*
+G01Y36830000D01*
+X21133000Y0D02*
+X27089000D01*
+X20650000Y483000D02*
+X21133000Y0D01*
+X10719000Y483000D02*
+X20650000D01*
+X10236000Y0D02*
+X10719000Y483000D01*
+X1100000Y0D02*
+X10236000D01*
+X24451000Y23500000D02*
+X26949000D01*
+X28008000Y1019000D02*
+Y22481000D01*
+X1042000Y23500000D02*
+X16078000D01*
+X16951000Y37745000D02*
+X23451000D01*
+X24451000Y23500000D02*
+Y36745000D01*
+X8000Y1034000D02*
+Y22466000D01*
+X16078000Y23500000D02*
+Y36618000D01*
+D11*
+X21519000Y18517000D02*
+G03I-945000D01*
+%TF.MD5,38bc3e94eca97f5a5e19c326598e4232*%
+M02*
diff --git a/gerbonara/gerber/utils.py b/gerbonara/gerber/utils.py
index 0627a6b..100e968 100644
--- a/gerbonara/gerber/utils.py
+++ b/gerbonara/gerber/utils.py
@@ -28,6 +28,9 @@ import re
from enum import Enum
from math import radians, sin, cos, sqrt, atan2, pi
+class UnknownStatementWarning(Warning):
+ pass
+
class RegexMatcher:
def __init__(self):
self.mapping = {}