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(); } }