Render PDFs in dynamic size

This commit is contained in:
Manuel Friedli 2020-10-03 22:33:58 +02:00
parent 93dd5a26fa
commit 74441c91cc
2 changed files with 26 additions and 18 deletions

View file

@ -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 = 20; int width = 50;
int height = 20; int height = 50;
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();

View file

@ -4,6 +4,7 @@ import lombok.NonNull;
import org.apache.pdfbox.pdmodel.PDDocument; import org.apache.pdfbox.pdmodel.PDDocument;
import org.apache.pdfbox.pdmodel.PDPage; import org.apache.pdfbox.pdmodel.PDPage;
import org.apache.pdfbox.pdmodel.PDPageContentStream; import org.apache.pdfbox.pdmodel.PDPageContentStream;
import org.apache.pdfbox.pdmodel.common.PDRectangle;
import java.awt.*; import java.awt.*;
import java.io.ByteArrayOutputStream; import java.io.ByteArrayOutputStream;
@ -22,17 +23,20 @@ public class PDFRenderer implements Renderer<byte[]> {
@Override @Override
@NonNull @NonNull
public byte[] render(@NonNull final Labyrinth labyrinth) { 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 PDDocument pdDocument = new PDDocument();
final PDPage page = new PDPage(); final PDPage page = new PDPage(new PDRectangle(pageWidth, pageHeight));
pdDocument.addPage(page); pdDocument.addPage(page);
try (PDPageContentStream pdPageContentStream = new PDPageContentStream(pdDocument, page)) { try (PDPageContentStream pdPageContentStream = new PDPageContentStream(pdDocument, page)) {
pdPageContentStream.setLineCapStyle(BasicStroke.CAP_BUTT); pdPageContentStream.setLineCapStyle(BasicStroke.CAP_ROUND);
pdPageContentStream.setLineJoinStyle(BasicStroke.JOIN_MITER); pdPageContentStream.setLineJoinStyle(BasicStroke.JOIN_MITER);
pdPageContentStream.setLineWidth(1.0f); pdPageContentStream.setLineWidth(1.0f);
pdPageContentStream.setStrokingColor(Color.BLACK); pdPageContentStream.setStrokingColor(Color.BLACK);
pdPageContentStream.setNonStrokingColor(Color.BLACK); pdPageContentStream.setNonStrokingColor(Color.BLACK);
final float scale = 10;
final float margin = 5;
this.drawHorizonzalLines(labyrinth, pdPageContentStream, margin, scale); this.drawHorizonzalLines(labyrinth, pdPageContentStream, margin, scale);
this.drawVerticalLines(labyrinth, pdPageContentStream, margin, scale); this.drawVerticalLines(labyrinth, pdPageContentStream, margin, scale);
} catch (IOException e) { } catch (IOException e) {
@ -49,25 +53,27 @@ public class PDFRenderer implements Renderer<byte[]> {
} }
private void drawHorizonzalLines(@NonNull final Labyrinth labyrinth, @NonNull final PDPageContentStream pdPageContentStream, final float margin, final float scale) throws IOException { 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++) { for (int y = 0; y < labyrinth.getHeight(); y++) {
boolean isPainting = false; boolean isPainting = false;
for (int x = 0; x < labyrinth.getWidth(); x++) { for (int x = 0; x < labyrinth.getWidth(); x++) {
final Tile currentTile = labyrinth.getTileAt(x, y); final Tile currentTile = labyrinth.getTileAt(x, y);
if (currentTile.hasWallAt(Direction.TOP)) { if (currentTile.hasWallAt(Direction.TOP)) {
if (!isPainting) { if (!isPainting) {
pdPageContentStream.moveTo(x * scale + margin, y * scale + margin); pdPageContentStream.moveTo(x * scale + margin, labyrinthHeight - y * scale + margin);
isPainting = true; isPainting = true;
} }
} else { } else {
if (isPainting) { if (isPainting) {
pdPageContentStream.lineTo(x * scale + margin, y * scale + margin); pdPageContentStream.lineTo(x * scale + margin, labyrinthHeight - y * scale + margin);
pdPageContentStream.stroke(); pdPageContentStream.stroke();
isPainting = false; isPainting = false;
} }
} }
} }
if (isPainting) { if (isPainting) {
pdPageContentStream.lineTo(labyrinth.getWidth() * scale + margin, y * scale + margin); pdPageContentStream.lineTo(labyrinth.getWidth() * scale + margin, labyrinthHeight - y * scale + margin);
pdPageContentStream.stroke(); pdPageContentStream.stroke();
} }
} }
@ -77,43 +83,45 @@ public class PDFRenderer implements Renderer<byte[]> {
final Tile currentTile = labyrinth.getTileAt(x, y - 1); final Tile currentTile = labyrinth.getTileAt(x, y - 1);
if (currentTile.hasWallAt(Direction.BOTTOM)) { if (currentTile.hasWallAt(Direction.BOTTOM)) {
if (!isPainting) { if (!isPainting) {
pdPageContentStream.moveTo(x * scale + margin, y * scale + margin); pdPageContentStream.moveTo(x * scale + margin, labyrinthHeight - y * scale + margin);
isPainting = true; isPainting = true;
} }
} else { } else {
if (isPainting) { if (isPainting) {
pdPageContentStream.lineTo(x * scale + margin, y * scale + margin); pdPageContentStream.lineTo(x * scale + margin, labyrinthHeight - y * scale + margin);
pdPageContentStream.stroke(); pdPageContentStream.stroke();
isPainting = false; isPainting = false;
} }
} }
} }
if (isPainting) { 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(); pdPageContentStream.stroke();
} }
} }
private void drawVerticalLines(@NonNull final Labyrinth labyrinth, @NonNull final PDPageContentStream pdPageContentStream, final float margin, final float scale) throws IOException { 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++) { for (int x = 0; x < labyrinth.getWidth(); x++) {
boolean isPainting = false; boolean isPainting = false;
for (int y = 0; y < labyrinth.getHeight(); y++) { for (int y = 0; y < labyrinth.getHeight(); y++) {
final Tile currentTile = labyrinth.getTileAt(x, y); final Tile currentTile = labyrinth.getTileAt(x, y);
if (currentTile.hasWallAt(Direction.LEFT)) { if (currentTile.hasWallAt(Direction.LEFT)) {
if (!isPainting) { if (!isPainting) {
pdPageContentStream.moveTo(x * scale + margin, y * scale + margin); pdPageContentStream.moveTo(x * scale + margin, labyrinthHeight - y * scale + margin);
isPainting = true; isPainting = true;
} }
} else { } else {
if (isPainting) { if (isPainting) {
pdPageContentStream.lineTo(x * scale + margin, y * scale + margin); pdPageContentStream.lineTo(x * scale + margin, labyrinthHeight - y * scale + margin);
pdPageContentStream.stroke(); pdPageContentStream.stroke();
isPainting = false; isPainting = false;
} }
} }
} }
if (isPainting) { if (isPainting) {
pdPageContentStream.lineTo(x * scale + margin, labyrinth.getHeight() * scale + margin); pdPageContentStream.lineTo(x * scale + margin, labyrinthHeight - labyrinth.getHeight() * scale + margin);
pdPageContentStream.stroke(); pdPageContentStream.stroke();
} }
} }
@ -123,19 +131,19 @@ public class PDFRenderer implements Renderer<byte[]> {
final Tile currentTile = labyrinth.getTileAt(x - 1, y); final Tile currentTile = labyrinth.getTileAt(x - 1, y);
if (currentTile.hasWallAt(Direction.RIGHT)) { if (currentTile.hasWallAt(Direction.RIGHT)) {
if (!isPainting) { if (!isPainting) {
pdPageContentStream.moveTo(x * scale + margin, y * scale + margin); pdPageContentStream.moveTo(x * scale + margin, labyrinthHeight - y * scale + margin);
isPainting = true; isPainting = true;
} }
} else { } else {
if (isPainting) { if (isPainting) {
pdPageContentStream.lineTo(x * scale + margin, y * scale + margin); pdPageContentStream.lineTo(x * scale + margin, labyrinthHeight - y * scale + margin);
pdPageContentStream.stroke(); pdPageContentStream.stroke();
isPainting = false; isPainting = false;
} }
} }
} }
if (isPainting) { 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(); pdPageContentStream.stroke();
} }
} }