mirror of
https://github.com/bancika/diy-layout-creator
synced 2026-11-13 02:32:09 +10:00
Resistors, capacitors, diodes, ICs, transistors and other PCB parts can be placed on the bottom of the board with the new 'Board Side' property; Gerber export puts their silkscreen on the bottom layer with the text mirrored
This commit is contained in:
@@ -162,13 +162,16 @@ public class GerberExporter {
|
||||
IGerberComponentSimple gerberComponentSimple = (IGerberComponentSimple) gerberComponent;
|
||||
GerberLayer layer = gerberComponentSimple.getGerberLayer();
|
||||
// components emit their top-side layer; a part mounted underneath goes to the bottom one
|
||||
if (c instanceof IBoardSideComponent
|
||||
&& ((IBoardSideComponent) c).getBoardSide() == PCBLayer._1) {
|
||||
boolean bottomSide = c instanceof IBoardSideComponent
|
||||
&& ((IBoardSideComponent) c).getBoardSide() == PCBLayer._1;
|
||||
if (bottomSide) {
|
||||
layer = layer.flip();
|
||||
}
|
||||
g2d.startGerberOutput(layer, gerberComponentSimple.getGerberFunction(),
|
||||
gerberComponentSimple.isGerberNegative());
|
||||
g2d.setMirrorText(bottomSide);
|
||||
c.draw(g2d, ComponentState.NORMAL, outlineMode, currentProject, g2d);
|
||||
g2d.setMirrorText(false);
|
||||
g2d.stopGerberOutput();
|
||||
}
|
||||
}
|
||||
|
||||
@@ -58,6 +58,7 @@ public class GerberG2DWrapper extends Graphics2D
|
||||
private double tolerance;
|
||||
|
||||
private Rectangle2D boardRect;
|
||||
private boolean mirrorText = false;
|
||||
|
||||
public GerberG2DWrapper(Graphics2D graphics2d, String diylcVersion, Rectangle2D boardRect) {
|
||||
super();
|
||||
@@ -154,6 +155,15 @@ public class GerberG2DWrapper extends Graphics2D
|
||||
return layerMap;
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets whether text is written mirrored, each string about its own centre. The output is in top
|
||||
* view, so text on the bottom side has to be mirrored to read correctly once the board is turned
|
||||
* over.
|
||||
*/
|
||||
public void setMirrorText(boolean mirrorText) {
|
||||
this.mirrorText = mirrorText;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void draw(Shape s) {
|
||||
if (trackingGerber && !getColor().equals(Constants.TRANSPARENT_COLOR)) {
|
||||
@@ -181,6 +191,10 @@ public class GerberG2DWrapper extends Graphics2D
|
||||
GlyphVector gv = font.createGlyphVector(graphics2d.getFontRenderContext(), str);
|
||||
|
||||
AffineTransform translateInstance = AffineTransform.getTranslateInstance(x, y);
|
||||
if (mirrorText) {
|
||||
translateInstance.translate(gv.getLogicalBounds().getWidth(), 0);
|
||||
translateInstance.scale(-1, 1);
|
||||
}
|
||||
|
||||
for (int i = 0; i < gv.getNumGlyphs(); i++) {
|
||||
Shape glyphShape = gv.getGlyphOutline(i);
|
||||
|
||||
@@ -22,12 +22,17 @@
|
||||
package org.diylc.core.gerber;
|
||||
|
||||
import static org.junit.Assert.assertEquals;
|
||||
import static org.junit.Assert.assertTrue;
|
||||
|
||||
import java.awt.Color;
|
||||
import java.awt.Font;
|
||||
import java.awt.Graphics2D;
|
||||
import java.awt.Shape;
|
||||
import java.awt.geom.Rectangle2D;
|
||||
import java.awt.image.BufferedImage;
|
||||
import java.util.ArrayList;
|
||||
import java.util.EnumSet;
|
||||
import java.util.List;
|
||||
|
||||
import org.diylc.common.PCBLayer;
|
||||
import org.diylc.core.ComponentState;
|
||||
@@ -74,6 +79,49 @@ public class GerberExporterTest {
|
||||
assertEquals(EnumSet.of(GerberLayer.SilkscreenTop), EnumSet.copyOf(g2d.getLayerMap().keySet()));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testTopSideTextReadsLeftToRight() {
|
||||
List<Rectangle2D> glyphs = drawText(PCBLayer._2);
|
||||
|
||||
assertTrue(glyphs.get(0).getMinX() < glyphs.get(1).getMinX());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testBottomSideTextIsMirrored() {
|
||||
List<Rectangle2D> top = drawText(PCBLayer._2);
|
||||
List<Rectangle2D> bottom = drawText(PCBLayer._1);
|
||||
|
||||
// seen from the top, the first letter of a bottom-side label is on the right
|
||||
assertTrue(bottom.get(0).getMinX() > bottom.get(1).getMinX());
|
||||
// mirrored about the centre of its layout box, so the text stays where it was; the glyphs'
|
||||
// uneven side bearings move their drawn bounds by a pixel or so
|
||||
assertEquals(union(top).getCenterX(), union(bottom).getCenterX(), 2);
|
||||
}
|
||||
|
||||
private static List<Rectangle2D> drawText(PCBLayer side) {
|
||||
List<Rectangle2D> glyphs = new ArrayList<Rectangle2D>();
|
||||
BufferedImage img = new BufferedImage(100, 100, BufferedImage.TYPE_INT_ARGB);
|
||||
Graphics2D graphics = img.createGraphics();
|
||||
GerberG2DWrapper g2d =
|
||||
new GerberG2DWrapper(graphics, "test", new Rectangle2D.Double(0, 0, 100, 100)) {
|
||||
@Override
|
||||
public void fillShape(Shape s) {
|
||||
glyphs.add(s.getBounds2D());
|
||||
}
|
||||
};
|
||||
GerberExporter.drawComponent(new Project(), g2d, new TextGerberComponent(side), false);
|
||||
graphics.dispose();
|
||||
return glyphs;
|
||||
}
|
||||
|
||||
private static Rectangle2D union(List<Rectangle2D> rects) {
|
||||
Rectangle2D union = (Rectangle2D) rects.get(0).clone();
|
||||
for (Rectangle2D rect : rects) {
|
||||
union.add(rect);
|
||||
}
|
||||
return union;
|
||||
}
|
||||
|
||||
private static GerberG2DWrapper draw(SimpleGerberComponent component) {
|
||||
BufferedImage img = new BufferedImage(100, 100, BufferedImage.TYPE_INT_ARGB);
|
||||
Graphics2D graphics = img.createGraphics();
|
||||
@@ -126,4 +174,21 @@ public class GerberExporterTest {
|
||||
return side;
|
||||
}
|
||||
}
|
||||
|
||||
public static class TextGerberComponent extends SidedGerberComponent {
|
||||
|
||||
private static final long serialVersionUID = 1L;
|
||||
|
||||
public TextGerberComponent(PCBLayer side) {
|
||||
super(side);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void draw(Graphics2D g2d, ComponentState componentState, boolean outlineMode,
|
||||
Project project, IDrawingObserver drawingObserver) {
|
||||
g2d.setColor(Color.black);
|
||||
g2d.setFont(new Font(Font.SANS_SERIF, Font.PLAIN, 20));
|
||||
g2d.drawString("AB", 10, 50);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user