Gerber export no longer cuts the holes of solder pads and vias out of the copper layers; the drill files alone define the holes

This commit is contained in:
Bane Stojkovic
2026-11-12 11:08:52 +01:00
parent 2439510f35
commit 34490b50b2
4 changed files with 37 additions and 9 deletions
@@ -125,16 +125,16 @@ public class SolderPad extends AbstractTransparentComponent<Void>
drawingObserver.stopDrawingSide();
drawingObserver.stopTracking();
drawingObserver.stopTrackingContinuityArea();
// the hole goes to the drill file only; cutting it out of the copper as well is advised against
// by the Gerber specification
if (gerberDrawingObserver != null) {
for (GerberLayer gerberCopperLayer : gerberCopperLayers) {
gerberDrawingObserver.stopGerberOutput(gerberCopperLayer);
gerberDrawingObserver.stopGerberOutput(getMaskLayer(gerberCopperLayer));
}
}
if (getHoleSize().getValue() > 0 && !HoleType.NONE.equals(getHoleType())) {
if (gerberDrawingObserver != null) {
for (GerberLayer gerberCopperLayer : gerberCopperLayers) {
gerberDrawingObserver.setGerberNegative(gerberCopperLayer, true);
}
GerberLayer holeLayer = HoleType.PTH.equals(getHoleType()) ? GerberLayer.DrillPlated : GerberLayer.DrillNonPlated;
gerberDrawingObserver.startGerberOutput(holeLayer, GerberFunctions.COMPONENT_DRILL, false);
}
@@ -107,9 +107,11 @@ public class Via extends AbstractTransparentComponent<Void>
diameter, diameter));
drawingObserver.stopTracking();
drawingObserver.stopTrackingContinuityArea();
// the hole goes to the drill file only; cutting it out of the copper as well is advised against
// by the Gerber specification
if (gerberDrawingObserver != null) {
gerberDrawingObserver.setGerberNegative(GerberLayer.CopperTop, true);
gerberDrawingObserver.setGerberNegative(GerberLayer.CopperBot, true);
gerberDrawingObserver.stopGerberOutput(GerberLayer.CopperTop);
gerberDrawingObserver.stopGerberOutput(GerberLayer.CopperBot);
gerberDrawingObserver.startGerberOutput(GerberLayer.DrillPlated, VIA_DRILL, false);
}
g2d.setColor(Constants.CANVAS_COLOR);
@@ -21,13 +21,17 @@
*/
package org.diylc.components.connectivity;
import static org.junit.Assert.assertFalse;
import static org.junit.Assert.assertTrue;
import java.awt.Graphics2D;
import java.awt.geom.Rectangle2D;
import java.awt.image.BufferedImage;
import java.util.Map;
import java.util.Set;
import com.bancika.gerberwriter.DataLayer;
import org.diylc.common.PCBLayer;
import org.diylc.core.ComponentState;
import org.diylc.core.Project;
@@ -75,7 +79,7 @@ public class SolderPadGerberTest {
@Test
public void testViaIsOnBothLayersAndTented() {
Via via = new Via();
Set<GerberLayer> layers = drawGerber(via);
Set<GerberLayer> layers = drawGerber(via).keySet();
assertTrue(layers.contains(GerberLayer.CopperTop));
assertTrue(layers.contains(GerberLayer.CopperBot));
assertTrue(layers.contains(GerberLayer.DrillPlated));
@@ -83,6 +87,24 @@ public class SolderPadGerberTest {
assertTrue(!layers.contains(GerberLayer.SolderMaskBot));
}
@Test
public void testHolesAreNotCutOutOfCopper() {
SolderPad pad = new SolderPad();
pad.setHoleType(SolderPad.HoleType.PTH);
assertNoCutOut(drawGerber(pad));
assertNoCutOut(drawGerber(new Via()));
}
// a cut-out is drawn with clear polarity, %LPC*%
private static void assertNoCutOut(Map<GerberLayer, DataLayer> layers) {
for (GerberLayer copperLayer : new GerberLayer[] {GerberLayer.CopperTop,
GerberLayer.CopperBot}) {
String gerber = layers.get(copperLayer).dumpGerberToString();
assertTrue(gerber.contains("D03*"));
assertFalse(gerber.contains("%LPC*%"));
}
}
private static Set<GerberLayer> drawGerber(PCBLayer layer) {
return drawGerber(layer, SolderPad.HoleType.NTPH);
}
@@ -91,10 +113,10 @@ public class SolderPadGerberTest {
SolderPad pad = new SolderPad();
pad.setLayer(layer);
pad.setHoleType(holeType);
return drawGerber(pad);
return drawGerber(pad).keySet();
}
private static Set<GerberLayer> drawGerber(IGerberComponentCustom component) {
private static Map<GerberLayer, DataLayer> drawGerber(IGerberComponentCustom component) {
BufferedImage img = new BufferedImage(100, 100, BufferedImage.TYPE_INT_ARGB);
Graphics2D graphics = img.createGraphics();
GerberG2DWrapper g2d =
@@ -102,6 +124,6 @@ public class SolderPadGerberTest {
g2d.startedDrawingComponent();
component.draw(g2d, ComponentState.NORMAL, false, new Project(), g2d, g2d);
graphics.dispose();
return g2d.getLayerMap().keySet();
return g2d.getLayerMap();
}
}