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…
	
	Add table
		Add a link
		
	
		Reference in a new issue