Add (very simple) PDF renderer.
Some checks failed
continuous-integration/drone/push Build is failing
Some checks failed
continuous-integration/drone/push Build is failing
This commit is contained in:
parent
5d07cfe1fc
commit
93dd5a26fa
4 changed files with 209 additions and 2 deletions
5
pom.xml
5
pom.xml
|
@ -25,6 +25,11 @@
|
||||||
<groupId>io.vavr</groupId>
|
<groupId>io.vavr</groupId>
|
||||||
<artifactId>vavr</artifactId>
|
<artifactId>vavr</artifactId>
|
||||||
</dependency>
|
</dependency>
|
||||||
|
<dependency>
|
||||||
|
<groupId>org.apache.pdfbox</groupId>
|
||||||
|
<artifactId>pdfbox</artifactId>
|
||||||
|
<version>2.0.20</version>
|
||||||
|
</dependency>
|
||||||
<dependency>
|
<dependency>
|
||||||
<groupId>org.junit.jupiter</groupId>
|
<groupId>org.junit.jupiter</groupId>
|
||||||
<artifactId>junit-jupiter-api</artifactId>
|
<artifactId>junit-jupiter-api</artifactId>
|
||||||
|
|
|
@ -7,8 +7,8 @@ import java.nio.file.Paths;
|
||||||
|
|
||||||
public class Main {
|
public class Main {
|
||||||
public static void main(@NonNull final String[] args) {
|
public static void main(@NonNull final String[] args) {
|
||||||
int width = 80;
|
int width = 20;
|
||||||
int height = 40;
|
int height = 20;
|
||||||
final Labyrinth labyrinth = new Labyrinth(width, height);
|
final Labyrinth labyrinth = new Labyrinth(width, height);
|
||||||
final TextRenderer textRenderer = TextRenderer.newInstance();
|
final TextRenderer textRenderer = TextRenderer.newInstance();
|
||||||
final HTMLRenderer htmlRenderer = HTMLRenderer.newInstance();
|
final HTMLRenderer htmlRenderer = HTMLRenderer.newInstance();
|
||||||
|
@ -18,6 +18,8 @@ public class Main {
|
||||||
.setTargetSolutionFile(userHome.resolve("labyrinth-solution.txt"));
|
.setTargetSolutionFile(userHome.resolve("labyrinth-solution.txt"));
|
||||||
final HTMLFileRenderer htmlFileRenderer = HTMLFileRenderer.newInstance()
|
final HTMLFileRenderer htmlFileRenderer = HTMLFileRenderer.newInstance()
|
||||||
.setTargetFile(userHome.resolve("labyrinth.html"));
|
.setTargetFile(userHome.resolve("labyrinth.html"));
|
||||||
|
final PDFFileRenderer pdfFileRenderer = PDFFileRenderer.newInstance().setTargetFile(userHome.resolve("labyrinth.pdf"));
|
||||||
|
|
||||||
// Render Labyrinth to stdout
|
// Render Labyrinth to stdout
|
||||||
System.out.println(textRenderer.render(labyrinth));
|
System.out.println(textRenderer.render(labyrinth));
|
||||||
// Render Labyrinth solution to stdout
|
// Render Labyrinth solution to stdout
|
||||||
|
@ -28,5 +30,7 @@ public class Main {
|
||||||
System.out.println(textFileRenderer.render(labyrinth));
|
System.out.println(textFileRenderer.render(labyrinth));
|
||||||
// Render HTML to file
|
// Render HTML to file
|
||||||
System.out.println(htmlFileRenderer.render(labyrinth));
|
System.out.println(htmlFileRenderer.render(labyrinth));
|
||||||
|
// Render PDF to file
|
||||||
|
System.out.println(pdfFileRenderer.render(labyrinth));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
56
src/main/java/ch/fritteli/labyrinth/PDFFileRenderer.java
Normal file
56
src/main/java/ch/fritteli/labyrinth/PDFFileRenderer.java
Normal file
|
@ -0,0 +1,56 @@
|
||||||
|
package ch.fritteli.labyrinth;
|
||||||
|
|
||||||
|
import lombok.NonNull;
|
||||||
|
|
||||||
|
import java.io.IOException;
|
||||||
|
import java.nio.file.Files;
|
||||||
|
import java.nio.file.Path;
|
||||||
|
|
||||||
|
public class PDFFileRenderer implements Renderer<Path> {
|
||||||
|
@NonNull
|
||||||
|
private static final PDFRenderer PDF_RENDERER = PDFRenderer.newInstance();
|
||||||
|
private Path targetFile;
|
||||||
|
|
||||||
|
private PDFFileRenderer() {
|
||||||
|
try {
|
||||||
|
this.targetFile = Files.createTempFile("labyrinth_", ".pdf");
|
||||||
|
} catch (IOException e) {
|
||||||
|
System.err.println("Unable to set default target file.");
|
||||||
|
e.printStackTrace();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@NonNull
|
||||||
|
public static PDFFileRenderer newInstance() {
|
||||||
|
return new PDFFileRenderer();
|
||||||
|
}
|
||||||
|
|
||||||
|
public boolean isTargetFileDefinedAndWritable() {
|
||||||
|
return this.targetFile != null && this.targetFile.toFile().canWrite();
|
||||||
|
}
|
||||||
|
|
||||||
|
@NonNull
|
||||||
|
public PDFFileRenderer setTargetFile(@NonNull final Path targetFile) {
|
||||||
|
this.targetFile = targetFile;
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public Path render(@NonNull final Labyrinth labyrinth) {
|
||||||
|
if (!this.isTargetFileDefinedAndWritable()) {
|
||||||
|
try {
|
||||||
|
Files.createFile(this.targetFile);
|
||||||
|
} catch (IOException e) {
|
||||||
|
throw new IllegalArgumentException("Cannot write to target file.", e);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
final byte[] bytes = PDF_RENDERER.render(labyrinth);
|
||||||
|
try {
|
||||||
|
Files.write(this.targetFile, bytes);
|
||||||
|
} catch (IOException e) {
|
||||||
|
System.err.println("Failed writing to file " + this.targetFile.normalize().toString());
|
||||||
|
e.printStackTrace();
|
||||||
|
}
|
||||||
|
return this.targetFile;
|
||||||
|
}
|
||||||
|
}
|
142
src/main/java/ch/fritteli/labyrinth/PDFRenderer.java
Normal file
142
src/main/java/ch/fritteli/labyrinth/PDFRenderer.java
Normal file
|
@ -0,0 +1,142 @@
|
||||||
|
package ch.fritteli.labyrinth;
|
||||||
|
|
||||||
|
import lombok.NonNull;
|
||||||
|
import org.apache.pdfbox.pdmodel.PDDocument;
|
||||||
|
import org.apache.pdfbox.pdmodel.PDPage;
|
||||||
|
import org.apache.pdfbox.pdmodel.PDPageContentStream;
|
||||||
|
|
||||||
|
import java.awt.*;
|
||||||
|
import java.io.ByteArrayOutputStream;
|
||||||
|
import java.io.IOException;
|
||||||
|
|
||||||
|
public class PDFRenderer implements Renderer<byte[]> {
|
||||||
|
private PDFRenderer() {
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
@NonNull
|
||||||
|
public static PDFRenderer newInstance() {
|
||||||
|
return new PDFRenderer();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
@NonNull
|
||||||
|
public byte[] render(@NonNull final Labyrinth labyrinth) {
|
||||||
|
final PDDocument pdDocument = new PDDocument();
|
||||||
|
final PDPage page = new PDPage();
|
||||||
|
pdDocument.addPage(page);
|
||||||
|
try (PDPageContentStream pdPageContentStream = new PDPageContentStream(pdDocument, page)) {
|
||||||
|
pdPageContentStream.setLineCapStyle(BasicStroke.CAP_BUTT);
|
||||||
|
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) {
|
||||||
|
e.printStackTrace();
|
||||||
|
}
|
||||||
|
final ByteArrayOutputStream output = new ByteArrayOutputStream();
|
||||||
|
try {
|
||||||
|
pdDocument.save(output);
|
||||||
|
pdDocument.close();
|
||||||
|
} catch (IOException e) {
|
||||||
|
e.printStackTrace();
|
||||||
|
}
|
||||||
|
return output.toByteArray();
|
||||||
|
}
|
||||||
|
|
||||||
|
private void drawHorizonzalLines(@NonNull final Labyrinth labyrinth, @NonNull final PDPageContentStream pdPageContentStream, final float margin, final float scale) throws IOException {
|
||||||
|
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);
|
||||||
|
isPainting = true;
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
if (isPainting) {
|
||||||
|
pdPageContentStream.lineTo(x * scale + margin, y * scale + margin);
|
||||||
|
pdPageContentStream.stroke();
|
||||||
|
isPainting = false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (isPainting) {
|
||||||
|
pdPageContentStream.lineTo(labyrinth.getWidth() * scale + margin, y * scale + margin);
|
||||||
|
pdPageContentStream.stroke();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
boolean isPainting = false;
|
||||||
|
int y = labyrinth.getHeight();
|
||||||
|
for (int x = 0; x < labyrinth.getWidth(); x++) {
|
||||||
|
final Tile currentTile = labyrinth.getTileAt(x, y - 1);
|
||||||
|
if (currentTile.hasWallAt(Direction.BOTTOM)) {
|
||||||
|
if (!isPainting) {
|
||||||
|
pdPageContentStream.moveTo(x * scale + margin, y * scale + margin);
|
||||||
|
isPainting = true;
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
if (isPainting) {
|
||||||
|
pdPageContentStream.lineTo(x * scale + margin, y * scale + margin);
|
||||||
|
pdPageContentStream.stroke();
|
||||||
|
isPainting = false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (isPainting) {
|
||||||
|
pdPageContentStream.lineTo(labyrinth.getWidth() * scale + margin, 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 {
|
||||||
|
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);
|
||||||
|
isPainting = true;
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
if (isPainting) {
|
||||||
|
pdPageContentStream.lineTo(x * scale + margin, y * scale + margin);
|
||||||
|
pdPageContentStream.stroke();
|
||||||
|
isPainting = false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (isPainting) {
|
||||||
|
pdPageContentStream.lineTo(x * scale + margin, labyrinth.getHeight() * scale + margin);
|
||||||
|
pdPageContentStream.stroke();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
boolean isPainting = false;
|
||||||
|
int x = labyrinth.getWidth();
|
||||||
|
for (int y = 0; y < labyrinth.getHeight(); y++) {
|
||||||
|
final Tile currentTile = labyrinth.getTileAt(x - 1, y);
|
||||||
|
if (currentTile.hasWallAt(Direction.RIGHT)) {
|
||||||
|
if (!isPainting) {
|
||||||
|
pdPageContentStream.moveTo(x * scale + margin, y * scale + margin);
|
||||||
|
isPainting = true;
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
if (isPainting) {
|
||||||
|
pdPageContentStream.lineTo(x * scale + margin, y * scale + margin);
|
||||||
|
pdPageContentStream.stroke();
|
||||||
|
isPainting = false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (isPainting) {
|
||||||
|
pdPageContentStream.lineTo(labyrinth.getWidth() * scale + margin, labyrinth.getHeight() * scale + margin);
|
||||||
|
pdPageContentStream.stroke();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
Loading…
Reference in a new issue