diff --git a/diylc/diylc-core/src/main/resources/update.xml b/diylc/diylc-core/src/main/resources/update.xml
index 84997ad8c..78f693609 100644
--- a/diylc/diylc-core/src/main/resources/update.xml
+++ b/diylc/diylc-core/src/main/resources/update.xml
@@ -669,6 +669,10 @@
IMPROVEMENT
A 'Solder Pad' with a plated through hole now has copper on both layers, like the real thing, and joins top and bottom copper in netlists and 'Highlight Connected Areas'; Gerber export writes it to both copper and both solder mask layers
+
+ IMPROVEMENT
+ Gerber export no longer cuts the holes of solder pads and vias out of the copper layers; the holes are defined by the drill files alone, as the Gerber specification recommends
+
BUG_FIX
Rotated labels in pasted components and building blocks were drawn in the wrong place and at the wrong angle while following the mouse, until the components were placed
diff --git a/diylc/diylc-library/src/main/java/org/diylc/components/connectivity/SolderPad.java b/diylc/diylc-library/src/main/java/org/diylc/components/connectivity/SolderPad.java
index 713f92c21..40ba75b2d 100644
--- a/diylc/diylc-library/src/main/java/org/diylc/components/connectivity/SolderPad.java
+++ b/diylc/diylc-library/src/main/java/org/diylc/components/connectivity/SolderPad.java
@@ -125,16 +125,16 @@ public class SolderPad extends AbstractTransparentComponent
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);
}
diff --git a/diylc/diylc-library/src/main/java/org/diylc/components/connectivity/Via.java b/diylc/diylc-library/src/main/java/org/diylc/components/connectivity/Via.java
index 5981267ac..01261a6e4 100644
--- a/diylc/diylc-library/src/main/java/org/diylc/components/connectivity/Via.java
+++ b/diylc/diylc-library/src/main/java/org/diylc/components/connectivity/Via.java
@@ -107,9 +107,11 @@ public class Via extends AbstractTransparentComponent
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);
diff --git a/diylc/diylc-library/src/test/java/org/diylc/components/connectivity/SolderPadGerberTest.java b/diylc/diylc-library/src/test/java/org/diylc/components/connectivity/SolderPadGerberTest.java
index 859938a29..89b7361f7 100644
--- a/diylc/diylc-library/src/test/java/org/diylc/components/connectivity/SolderPadGerberTest.java
+++ b/diylc/diylc-library/src/test/java/org/diylc/components/connectivity/SolderPadGerberTest.java
@@ -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 layers = drawGerber(via);
+ Set 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 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 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 drawGerber(IGerberComponentCustom component) {
+ private static Map 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();
}
}