Skip to content

Commit

Permalink
Add support for Altium implied leading zeros omitted (#340)
Browse files Browse the repository at this point in the history
Altium generates files with format specification `%FSAX...Y...%` (no `L` for leading zero omission). This change updates the grammar to accept an empty Zeros parameter defaulting to lead zero omission.
  • Loading branch information
sjgallagher2 authored Nov 19, 2024
1 parent 5de1bd8 commit f39c223
Show file tree
Hide file tree
Showing 7 changed files with 124 additions and 3 deletions.
3 changes: 2 additions & 1 deletion .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -260,11 +260,12 @@ cython_debug/
# be found at https://github.com/github/gitignore/blob/main/Global/JetBrains.gitignore
# and can be added to the global gitignore or merged into this file. For a more nuclear
# option (not recommended) you can uncomment the following to ignore the entire idea folder.
#.idea/
.idea/

### Python Patch ###
# Poetry local configuration file - https://python-poetry.org/docs/configuration/#local-configuration
poetry.toml
A

# ruff
.ruff_cache/
Expand Down
3 changes: 3 additions & 0 deletions src/pygerber/gerber/ast/nodes/enums.py
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,9 @@ class Zeros(Enum):
SKIP_TRAILING = "T"
"""Skip trailing zeros mode."""

SKIP_LEADING_IMPLIED = ""
"""Implied skip leading zeros mode."""

def __repr__(self) -> str:
return f"{self.__class__.__name__}.{self.name}"

Expand Down
2 changes: 1 addition & 1 deletion src/pygerber/gerber/ast/state_tracking_visitor.py
Original file line number Diff line number Diff line change
Expand Up @@ -111,7 +111,7 @@ class CoordinateFormat(_StateModel):
def __init__(self, **kwargs: Any) -> None:
super().__init__(**kwargs)

if self.zeros == Zeros.SKIP_LEADING:
if self.zeros in (Zeros.SKIP_LEADING, Zeros.SKIP_LEADING_IMPLIED):
self.unpack_x = self._unpack_skip_leading(self.x_integral, self.x_decimal) # type: ignore[method-assign]
self.unpack_y = self._unpack_skip_leading(self.y_integral, self.y_decimal) # type: ignore[method-assign]
self.pack_x = self._pack_skip_leading(self.x_integral, self.x_decimal) # type: ignore[method-assign]
Expand Down
2 changes: 1 addition & 1 deletion src/pygerber/gerber/parser/pyparsing/grammar.py
Original file line number Diff line number Diff line change
Expand Up @@ -1762,7 +1762,7 @@ def fs(self) -> pp.ParserElement:
return (
self._extended_command(
pp.Literal("FS")
+ pp.one_of(("L", "T")).set_results_name("zeros")
+ pp.one_of(("L", "T", "")).set_results_name("zeros")
+ pp.one_of(("I", "A")).set_results_name("coordinate_mode")
+ pp.CaselessLiteral("X")
+ pp.Regex(r"[0-9]").set_results_name("x_integral")
Expand Down
54 changes: 54 additions & 0 deletions test/assets/gerberx3/issues/340/altium_example.grb
Original file line number Diff line number Diff line change
@@ -0,0 +1,54 @@
G04*
G04 #@! TF.GenerationSoftware,Altium Limited,Altium Designer,21.9.1 (22)*
G04*
G04 Layer_Physical_Order=1*
G04 Layer_Color=255*
%FSAX44Y44*%
%MOMM*%
G71*
G04*
G04 #@! TF.SameCoordinates,D1130218-381A-440B-BF67-0167512D4D43*
G04*
G04*
G04 #@! TF.FilePolarity,Positive*
G04*
G01*
G75*
%ADD14R,3.4000X1.5500*%
%ADD15C,1.5240*%
%ADD24C,1.0160*%
%ADD25R,1.3700X1.3700*%
%ADD26C,1.3700*%
%ADD27C,3.0000*%
%ADD28C,2.0320*%
%ADD29R,2.0320X2.0320*%
%ADD30C,7.0000*%
D14*
X01100000Y01800000D02*
D03*
Y01760000D02*
D03*
X00560000Y01660000D02*
D03*
Y01620000D02*
D03*
X00605000Y01660000D02*
D03*
Y01620000D02*
D03*
X00650000Y01660000D02*
D03*
Y01620000D02*
D03*
X00695000Y01660000D02*
D03*
Y01620000D02*
D03*
X00740000Y01660000D02*
D03*
Y01620000D02*
D03*
X00785000Y01660000D02*
D03*
Y01620000D02*
M02*
1 change: 1 addition & 0 deletions test/assets/gerberx3/tokens/properties/FSAX44Y44.grb
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
%FSAX44Y44*%
62 changes: 62 additions & 0 deletions test/unit/test_gerber/test_ast/test_state_tracking_visitor.py
Original file line number Diff line number Diff line change
Expand Up @@ -463,6 +463,14 @@ def test_d01_dispatch(
3,
7,
),
(
Zeros.SKIP_LEADING_IMPLIED,
CoordinateNotation.ABSOLUTE,
2,
6,
3,
7,
),
(
Zeros.SKIP_LEADING,
CoordinateNotation.INCREMENTAL,
Expand All @@ -479,6 +487,14 @@ def test_d01_dispatch(
3,
7,
),
(
Zeros.SKIP_LEADING_IMPLIED,
CoordinateNotation.INCREMENTAL,
2,
6,
3,
7,
),
],
)
def test_coordinate_format(
Expand Down Expand Up @@ -540,6 +556,15 @@ class TestCoordinateFormat:
y_decimal=6,
)

fmt_2 = FMT(
zeros=Zeros.SKIP_LEADING_IMPLIED,
coordinate_mode=CoordinateNotation.ABSOLUTE,
x_integral=2,
x_decimal=6,
y_integral=2,
y_decimal=6,
)

params_0: ClassVar[ParamsT] = [
(fmt_0, "0", 0),
(fmt_0, "1", 0.000001),
Expand Down Expand Up @@ -580,6 +605,13 @@ class TestCoordinateFormat:
(fmt_1, "+1", 10),
(fmt_1, "-1", -10),
(fmt_0, "-0", -0),
(fmt_2, "+", PackedCoordinateTooShortError),
(fmt_2, "+100000000", PackedCoordinateTooLongError),
(fmt_2, "", PackedCoordinateTooShortError),
(fmt_2, "100000001", PackedCoordinateTooLongError),
(fmt_2, "-", PackedCoordinateTooShortError),
(fmt_2, "-100000000", PackedCoordinateTooLongError),
(fmt_2, "-0", -0),
]
params_4: ClassVar[ParamsT] = [
(fmt_1, "00000001", 0.000001),
Expand Down Expand Up @@ -609,6 +641,36 @@ class TestCoordinateFormat:
(fmt_1, "-101", -10.1),
(fmt_1, "-11", -11),
]
params_7: ClassVar[ParamsT] = [
(fmt_2, "0", 0),
(fmt_2, "1", 0.000001),
(fmt_2, "11", 0.000011),
(fmt_2, "101", 0.000101),
(fmt_2, "1001", 0.001001),
(fmt_2, "10001", 0.010001),
(fmt_2, "100001", 0.100001),
(fmt_2, "1000001", 1.000001),
(fmt_2, "10000001", 10.000001),
]
params_8: ClassVar[ParamsT] = [
(fmt_2, "+0", 0),
(fmt_2, "+10", 0.00001),
(fmt_2, "+100", 0.0001),
(fmt_2, "+1000", 0.001),
(fmt_2, "+10000", 0.01),
(fmt_2, "+100000", 0.1),
(fmt_2, "+1000000", 1),
(fmt_2, "+10000000", 10),
]
params_9: ClassVar[ParamsT] = [
(fmt_2, "-10", -0.00001),
(fmt_2, "-100", -0.0001),
(fmt_2, "-1000", -0.001),
(fmt_2, "-10000", -0.01),
(fmt_2, "-100000", -0.1),
(fmt_2, "-1000000", -1),
(fmt_2, "-10000000", -10),
]

@pytest.mark.parametrize(
("fmt", "input_value", "expected"),
Expand Down

0 comments on commit f39c223

Please sign in to comment.