mirror of
https://github.com/bancika/diy-layout-creator
synced 2026-11-13 02:32:09 +10:00
The silkscreen print-out has a separate page for parts placed on the bottom of the board
This commit is contained in:
@@ -1,6 +1,8 @@
|
||||
package org.diylc.filter;
|
||||
|
||||
import org.diylc.common.PCBLayer;
|
||||
import org.diylc.core.IBoard;
|
||||
import org.diylc.core.IBoardSideComponent;
|
||||
import org.diylc.core.IDIYComponent;
|
||||
import org.diylc.core.gerber.GerberRenderMode;
|
||||
import org.diylc.core.gerber.IGerberComponent;
|
||||
@@ -9,6 +11,20 @@ import java.util.Set;
|
||||
|
||||
public class SilkScreenFilter implements IComponentFilter {
|
||||
|
||||
private PCBLayer side;
|
||||
|
||||
public SilkScreenFilter() {
|
||||
this(null);
|
||||
}
|
||||
|
||||
/**
|
||||
* @param side the side of the board whose silkscreen to keep, or null for both; board outlines
|
||||
* are kept on either side
|
||||
*/
|
||||
public SilkScreenFilter(PCBLayer side) {
|
||||
this.side = side;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean testComponent(IDIYComponent<?> component) {
|
||||
if (component instanceof IBoard board) {
|
||||
@@ -17,7 +33,16 @@ public class SilkScreenFilter implements IComponentFilter {
|
||||
if (!(component instanceof IGerberComponent gerberComponent)) {
|
||||
return false;
|
||||
}
|
||||
if (side != null && getSide(component) != side) {
|
||||
return false;
|
||||
}
|
||||
Set<GerberRenderMode> gerberRenderModes = gerberComponent.getGerberRenderModes();
|
||||
return gerberRenderModes.contains(GerberRenderMode.Outline);
|
||||
}
|
||||
|
||||
// components that do not say which side they are on are on top
|
||||
private static PCBLayer getSide(IDIYComponent<?> component) {
|
||||
return component instanceof IBoardSideComponent sided && sided.getBoardSide() == PCBLayer._1
|
||||
? PCBLayer._1 : PCBLayer._2;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -635,7 +635,7 @@
|
||||
</org.diylc.appframework.update.Change>
|
||||
<org.diylc.appframework.update.Change>
|
||||
<changeType>NEW_FEATURE</changeType>
|
||||
<description>Resistors, capacitors, diodes, ICs, transistors, switches, jacks, tube sockets and other PCB parts have a new 'Board Side' property to place them on the bottom of the board; bottom parts are drawn faded on the canvas and solid in the board's Underside Display, and Gerber export puts their silkscreen on the bottom layer with the text mirrored</description>
|
||||
<description>Resistors, capacitors, diodes, ICs, transistors, switches, jacks, tube sockets and other PCB parts have a new 'Board Side' property to place them on the bottom of the board; bottom parts are drawn faded on the canvas and solid in the board's Underside Display, and Gerber export puts their silkscreen on the bottom layer with the text mirrored, and the silkscreen print-out has a separate page for the bottom</description>
|
||||
</org.diylc.appframework.update.Change>
|
||||
<org.diylc.appframework.update.Change>
|
||||
<changeType>NEW_FEATURE</changeType>
|
||||
|
||||
@@ -0,0 +1,76 @@
|
||||
/*
|
||||
|
||||
DIY Layout Creator (DIYLC).
|
||||
Copyright (c) 2009-2025 held jointly by the individual authors.
|
||||
|
||||
This file is part of DIYLC.
|
||||
|
||||
DIYLC is free software: you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as published by
|
||||
the Free Software Foundation, either version 3 of the License, or
|
||||
(at your option) any later version.
|
||||
|
||||
DIYLC is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with DIYLC. If not, see <http://www.gnu.org/licenses/>.
|
||||
|
||||
*/
|
||||
package org.diylc.filter;
|
||||
|
||||
import static org.junit.Assert.assertTrue;
|
||||
|
||||
import org.diylc.common.PCBLayer;
|
||||
import org.diylc.core.gerber.GerberExporterTest.SidedGerberComponent;
|
||||
import org.diylc.core.gerber.GerberExporterTest.SimpleGerberComponent;
|
||||
import org.diylc.presenter.DrawingManagerTest.MockBoard;
|
||||
import org.junit.Test;
|
||||
|
||||
public class SilkScreenFilterTest {
|
||||
|
||||
@Test
|
||||
public void testPartsGoToTheirOwnSide() {
|
||||
SidedGerberComponent top = new SidedGerberComponent(PCBLayer._2);
|
||||
SidedGerberComponent bottom = new SidedGerberComponent(PCBLayer._1);
|
||||
|
||||
assertTrue(new SilkScreenFilter(PCBLayer._2).testComponent(top));
|
||||
assertTrue(!new SilkScreenFilter(PCBLayer._2).testComponent(bottom));
|
||||
assertTrue(new SilkScreenFilter(PCBLayer._1).testComponent(bottom));
|
||||
assertTrue(!new SilkScreenFilter(PCBLayer._1).testComponent(top));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testPartsWithoutSideAreOnTop() {
|
||||
SimpleGerberComponent part = new SimpleGerberComponent(null);
|
||||
|
||||
assertTrue(new SilkScreenFilter(PCBLayer._2).testComponent(part));
|
||||
assertTrue(!new SilkScreenFilter(PCBLayer._1).testComponent(part));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testBoardOutlineOnBothSides() {
|
||||
MockBoard board = new ExportedBoard();
|
||||
|
||||
assertTrue(new SilkScreenFilter(PCBLayer._2).testComponent(board));
|
||||
assertTrue(new SilkScreenFilter(PCBLayer._1).testComponent(board));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testNoSideKeepsEverything() {
|
||||
assertTrue(new SilkScreenFilter().testComponent(new SidedGerberComponent(PCBLayer._1)));
|
||||
assertTrue(new SilkScreenFilter().testComponent(new SidedGerberComponent(PCBLayer._2)));
|
||||
}
|
||||
|
||||
public static class ExportedBoard extends MockBoard {
|
||||
|
||||
private static final long serialVersionUID = 1L;
|
||||
|
||||
@Override
|
||||
public boolean shouldExportToGerber() {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
}
|
||||
+10
-1
@@ -23,6 +23,9 @@ package org.diylc.swing.plugins.file;
|
||||
|
||||
import org.diylc.common.DrawOption;
|
||||
import org.diylc.common.IPlugInPort;
|
||||
import org.diylc.common.PCBLayer;
|
||||
import org.diylc.core.IBoardSideComponent;
|
||||
import org.diylc.core.IDIYComponent;
|
||||
import org.diylc.filter.PCBLayerFilter;
|
||||
import org.diylc.filter.SilkScreenFilter;
|
||||
import org.diylc.swingframework.IDrawingProvider;
|
||||
@@ -53,11 +56,17 @@ public class SilkScreenDrawingProvider implements IDrawingProvider {
|
||||
@Override
|
||||
public void draw(int page, Graphics g, double zoomFactor) {
|
||||
plugInPort.draw((Graphics2D) g, EnumSet.of(DrawOption.ANTIALIASING, DrawOption.OUTLINE_MODE, DrawOption.MONOCHROMATIC),
|
||||
new SilkScreenFilter(), zoomFactor, null, null);
|
||||
new SilkScreenFilter(page == 0 ? PCBLayer._2 : PCBLayer._1), zoomFactor, null, null);
|
||||
}
|
||||
|
||||
// the top side, followed by the bottom side when a part is mounted there
|
||||
@Override
|
||||
public int getPageCount() {
|
||||
for (IDIYComponent<?> c : plugInPort.getCurrentProject().getComponents()) {
|
||||
if (c instanceof IBoardSideComponent && ((IBoardSideComponent) c).getBoardSide() == PCBLayer._1) {
|
||||
return 2;
|
||||
}
|
||||
}
|
||||
return 1;
|
||||
}
|
||||
}
|
||||
|
||||
+50
@@ -0,0 +1,50 @@
|
||||
/*
|
||||
|
||||
DIY Layout Creator (DIYLC).
|
||||
Copyright (c) 2009-2025 held jointly by the individual authors.
|
||||
|
||||
This file is part of DIYLC.
|
||||
|
||||
DIYLC is free software: you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as published by
|
||||
the Free Software Foundation, either version 3 of the License, or
|
||||
(at your option) any later version.
|
||||
|
||||
DIYLC is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with DIYLC. If not, see <http://www.gnu.org/licenses/>.
|
||||
|
||||
*/
|
||||
package org.diylc.swing.plugins.file;
|
||||
|
||||
import static org.junit.Assert.assertEquals;
|
||||
|
||||
import java.awt.Point;
|
||||
|
||||
import org.diylc.TestBase;
|
||||
import org.diylc.common.PCBLayer;
|
||||
import org.diylc.components.passive.Resistor;
|
||||
import org.junit.Test;
|
||||
|
||||
public class SilkScreenDrawingProviderTest extends TestBase {
|
||||
|
||||
@Test
|
||||
public void testOnePageWithoutBottomParts() {
|
||||
instantiateTwoClick("Passive", "Resistor", new Point(1000, 1000), new Point(1200, 1000));
|
||||
|
||||
assertEquals(1, new SilkScreenDrawingProvider(presenter).getPageCount());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testBottomPageForBottomParts() {
|
||||
instantiateTwoClick("Passive", "Resistor", new Point(1000, 1000), new Point(1200, 1000));
|
||||
Resistor resistor = (Resistor) presenter.getCurrentProject().getComponents().get(0);
|
||||
resistor.setBoardSide(PCBLayer._1);
|
||||
|
||||
assertEquals(2, new SilkScreenDrawingProvider(presenter).getPageCount());
|
||||
}
|
||||
}
|
||||
@@ -6,7 +6,8 @@ Gerber layers and the canvas shows it as a part on the far side of the board.
|
||||
Status: 45 parts have a Board Side property, and Gerber export sends a bottom-side part's
|
||||
silkscreen to the bottom layer with its text mirrored. Parts can be selected, dragged and stretched
|
||||
through the Underside Display mirror. The canvas draws a bottom-side part faded in the main view and
|
||||
solid in the mirror. The next steps below remain.
|
||||
solid in the mirror. The silkscreen print-out has a separate page for the bottom. The next steps
|
||||
below remain.
|
||||
|
||||
## 1. Current state
|
||||
|
||||
@@ -83,9 +84,11 @@ solid in the mirror. The next steps below remain.
|
||||
|
||||
### diylc-swing
|
||||
|
||||
- **PCB print-outs**: `SilkScreenDrawingProvider` prints one page of everything that has a
|
||||
silkscreen outline. Split it into top and bottom pages, filtered by side, the same way
|
||||
`TraceMaskDrawingProvider` gives one page per `PCBLayer`.
|
||||
- **PCB print-outs (done)**: `SilkScreenDrawingProvider` prints the top side, and a second page for
|
||||
the bottom when a part is mounted there, so a project without bottom parts still prints one page.
|
||||
`SilkScreenFilter` takes the side: a part with a Board Side goes on its own side's page, parts
|
||||
without one count as top, and board outlines go on both pages so that they line up. Neither
|
||||
page is mirrored or captioned, the same as the trace-mask pages.
|
||||
|
||||
### Editing through the Underside Display mirror
|
||||
|
||||
@@ -137,6 +140,8 @@ order.
|
||||
|
||||
- `GerberLayerTest` covers `flip()`. `GerberExporterTest` covers the dispatch for simple components,
|
||||
including a stub `IBoardSideComponent` on top, bottom and `null`.
|
||||
- `SilkScreenFilterTest` covers which side's page each part and board outline goes on, and
|
||||
`SilkScreenDrawingProviderTest` checks that the bottom page appears only for a bottom part.
|
||||
- `DrawingManagerTest` checks rendered pixels for a part that reports its own side: a bottom part
|
||||
is faded only with `FADE_FAR_SIDE`, also when drawn from the image cache; it is solid in the
|
||||
mirror, where a top part is faded; and a locked bottom part is faded once, not twice.
|
||||
@@ -156,6 +161,5 @@ order.
|
||||
|
||||
## 6. Next steps
|
||||
|
||||
1. Split the silkscreen print-out by side.
|
||||
2. Mirror stage 3: placing in the mirror.
|
||||
3. Run the regression suite.
|
||||
1. Mirror stage 3: placing in the mirror.
|
||||
2. Run the regression suite.
|
||||
|
||||
Reference in New Issue
Block a user