diff --git a/src/main/java/ch/fritteli/labyrinth/Main.java b/src/main/java/ch/fritteli/labyrinth/Main.java index e760bb7..1f7c050 100644 --- a/src/main/java/ch/fritteli/labyrinth/Main.java +++ b/src/main/java/ch/fritteli/labyrinth/Main.java @@ -7,8 +7,8 @@ import java.nio.file.Paths; public class Main { public static void main(@NonNull final String[] args) { - int width = 20; - int height = 20; + int width = 50; + int height = 50; final Labyrinth labyrinth = new Labyrinth(width, height); final TextRenderer textRenderer = TextRenderer.newInstance(); final HTMLRenderer htmlRenderer = HTMLRenderer.newInstance(); diff --git a/src/main/java/ch/fritteli/labyrinth/PDFRenderer.java b/src/main/java/ch/fritteli/labyrinth/PDFRenderer.java index abce7a9..5dad450 100644 --- a/src/main/java/ch/fritteli/labyrinth/PDFRenderer.java +++ b/src/main/java/ch/fritteli/labyrinth/PDFRenderer.java @@ -4,6 +4,7 @@ import lombok.NonNull; import org.apache.pdfbox.pdmodel.PDDocument; import org.apache.pdfbox.pdmodel.PDPage; import org.apache.pdfbox.pdmodel.PDPageContentStream; +import org.apache.pdfbox.pdmodel.common.PDRectangle; import java.awt.*; import java.io.ByteArrayOutputStream; @@ -22,17 +23,20 @@ public class PDFRenderer implements Renderer { @Override @NonNull public byte[] render(@NonNull final Labyrinth labyrinth) { + final float scale = 10; + final float margin = 5; + final float pageWidth = labyrinth.getWidth() * scale + 2 * margin; + final float pageHeight = labyrinth.getHeight() * scale + 2 * margin; + final PDDocument pdDocument = new PDDocument(); - final PDPage page = new PDPage(); + final PDPage page = new PDPage(new PDRectangle(pageWidth, pageHeight)); pdDocument.addPage(page); try (PDPageContentStream pdPageContentStream = new PDPageContentStream(pdDocument, page)) { - pdPageContentStream.setLineCapStyle(BasicStroke.CAP_BUTT); + pdPageContentStream.setLineCapStyle(BasicStroke.CAP_ROUND); pdPageContentStream.setLineJoinStyle(BasicStroke.JOIN_MITER); pdPageContentStream.setLineWidth(1.0f); pdPageContentStream.setStrokingColor(Color.BLACK); pdPageContentStream.setNonStrokingColor(Color.BLACK); - final float scale = 10; - final float margin = 5; this.drawHorizonzalLines(labyrinth, pdPageContentStream, margin, scale); this.drawVerticalLines(labyrinth, pdPageContentStream, margin, scale); } catch (IOException e) { @@ -49,25 +53,27 @@ public class PDFRenderer implements Renderer { } private void drawHorizonzalLines(@NonNull final Labyrinth labyrinth, @NonNull final PDPageContentStream pdPageContentStream, final float margin, final float scale) throws IOException { + // PDF has the origin in the lower left corner. We want it in the upper left corner, hence some magic is required. + final float labyrinthHeight = labyrinth.getHeight() * scale; for (int y = 0; y < labyrinth.getHeight(); y++) { boolean isPainting = false; for (int x = 0; x < labyrinth.getWidth(); x++) { final Tile currentTile = labyrinth.getTileAt(x, y); if (currentTile.hasWallAt(Direction.TOP)) { if (!isPainting) { - pdPageContentStream.moveTo(x * scale + margin, y * scale + margin); + pdPageContentStream.moveTo(x * scale + margin, labyrinthHeight - y * scale + margin); isPainting = true; } } else { if (isPainting) { - pdPageContentStream.lineTo(x * scale + margin, y * scale + margin); + pdPageContentStream.lineTo(x * scale + margin, labyrinthHeight - y * scale + margin); pdPageContentStream.stroke(); isPainting = false; } } } if (isPainting) { - pdPageContentStream.lineTo(labyrinth.getWidth() * scale + margin, y * scale + margin); + pdPageContentStream.lineTo(labyrinth.getWidth() * scale + margin, labyrinthHeight - y * scale + margin); pdPageContentStream.stroke(); } } @@ -77,43 +83,45 @@ public class PDFRenderer implements Renderer { final Tile currentTile = labyrinth.getTileAt(x, y - 1); if (currentTile.hasWallAt(Direction.BOTTOM)) { if (!isPainting) { - pdPageContentStream.moveTo(x * scale + margin, y * scale + margin); + pdPageContentStream.moveTo(x * scale + margin, labyrinthHeight - y * scale + margin); isPainting = true; } } else { if (isPainting) { - pdPageContentStream.lineTo(x * scale + margin, y * scale + margin); + pdPageContentStream.lineTo(x * scale + margin, labyrinthHeight - y * scale + margin); pdPageContentStream.stroke(); isPainting = false; } } } if (isPainting) { - pdPageContentStream.lineTo(labyrinth.getWidth() * scale + margin, labyrinth.getHeight() * scale + margin); + pdPageContentStream.lineTo(labyrinth.getWidth() * scale + margin, labyrinthHeight - labyrinth.getHeight() * scale + margin); pdPageContentStream.stroke(); } } private void drawVerticalLines(@NonNull final Labyrinth labyrinth, @NonNull final PDPageContentStream pdPageContentStream, final float margin, final float scale) throws IOException { + // PDF has the origin in the lower left corner. We want it in the upper left corner, hence some magic is required. + final float labyrinthHeight = labyrinth.getHeight() * scale; for (int x = 0; x < labyrinth.getWidth(); x++) { boolean isPainting = false; for (int y = 0; y < labyrinth.getHeight(); y++) { final Tile currentTile = labyrinth.getTileAt(x, y); if (currentTile.hasWallAt(Direction.LEFT)) { if (!isPainting) { - pdPageContentStream.moveTo(x * scale + margin, y * scale + margin); + pdPageContentStream.moveTo(x * scale + margin, labyrinthHeight - y * scale + margin); isPainting = true; } } else { if (isPainting) { - pdPageContentStream.lineTo(x * scale + margin, y * scale + margin); + pdPageContentStream.lineTo(x * scale + margin, labyrinthHeight - y * scale + margin); pdPageContentStream.stroke(); isPainting = false; } } } if (isPainting) { - pdPageContentStream.lineTo(x * scale + margin, labyrinth.getHeight() * scale + margin); + pdPageContentStream.lineTo(x * scale + margin, labyrinthHeight - labyrinth.getHeight() * scale + margin); pdPageContentStream.stroke(); } } @@ -123,19 +131,19 @@ public class PDFRenderer implements Renderer { final Tile currentTile = labyrinth.getTileAt(x - 1, y); if (currentTile.hasWallAt(Direction.RIGHT)) { if (!isPainting) { - pdPageContentStream.moveTo(x * scale + margin, y * scale + margin); + pdPageContentStream.moveTo(x * scale + margin, labyrinthHeight - y * scale + margin); isPainting = true; } } else { if (isPainting) { - pdPageContentStream.lineTo(x * scale + margin, y * scale + margin); + pdPageContentStream.lineTo(x * scale + margin, labyrinthHeight - y * scale + margin); pdPageContentStream.stroke(); isPainting = false; } } } if (isPainting) { - pdPageContentStream.lineTo(labyrinth.getWidth() * scale + margin, labyrinth.getHeight() * scale + margin); + pdPageContentStream.lineTo(labyrinth.getWidth() * scale + margin, labyrinthHeight - labyrinth.getHeight() * scale + margin); pdPageContentStream.stroke(); } }