Skip to content

Commit

Permalink
#427 API for getting the last y position and more
Browse files Browse the repository at this point in the history
Including the page positions of all layers. By popular demand!
  • Loading branch information
danfickle committed Mar 9, 2021
1 parent 138b5b9 commit 214a21a
Show file tree
Hide file tree
Showing 7 changed files with 391 additions and 13 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -13,13 +13,19 @@
import java.io.StringWriter;
import java.nio.file.Files;
import java.util.HashMap;
import java.util.List;
import java.util.Locale;
import java.util.Map;
import java.util.logging.Level;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
import java.util.stream.Collectors;

import javax.imageio.ImageIO;

import com.openhtmltopdf.util.Diagnostic;

import org.apache.pdfbox.io.IOUtils;
import org.w3c.dom.Element;

import com.openhtmltopdf.bidi.support.ICUBidiReorderer;
Expand All @@ -30,8 +36,11 @@
import com.openhtmltopdf.extend.FSTextBreaker;
import com.openhtmltopdf.extend.OutputDevice;
import com.openhtmltopdf.outputdevice.helper.BaseRendererBuilder.TextDirection;
import com.openhtmltopdf.pdfboxout.visualtester.PdfVisualTester;
import com.openhtmltopdf.pdfboxout.visualtester.PdfVisualTester.PdfCompareResult;
import com.openhtmltopdf.render.RenderingContext;
import com.openhtmltopdf.svgsupport.BatikSVGDrawer;
import com.openhtmltopdf.testcases.TestcaseRunner;
import com.openhtmltopdf.util.XRLogger;
import com.openhtmltopdf.visualtest.Java2DVisualTester.Java2DBuilderConfig;
import com.openhtmltopdf.visualtest.VisualTester.BuilderConfig;
Expand Down Expand Up @@ -230,4 +239,42 @@ public boolean isReplacedObject(Element e) {
}

public static final BuilderConfig WITH_SHAPES_DRAWER = (builder) -> { builder.useObjectDrawerFactory(new ShapesObjectDrawerFactory()); };

public static boolean comparePdfs(byte[] actualPdfBytes, String resource) throws IOException {
File outputPath = new File("target/test/visual-tests/test-output/");

byte[] expectedPdfBytes;
try (InputStream expectedIs = TestcaseRunner.class.getResourceAsStream("/visualtest/expected/" + resource + ".pdf")) {
expectedPdfBytes = IOUtils.toByteArray(expectedIs);
}

List<PdfCompareResult> problems = PdfVisualTester.comparePdfDocuments(expectedPdfBytes, actualPdfBytes, resource, false);

if (!problems.isEmpty()) {
System.err.println("Found problems with test case (" + resource + "):");
System.err.println(problems.stream().map(p -> p.logMessage).collect(Collectors.joining("\n ", "[\n ", "\n]")));

File outPdf = new File(outputPath, resource + "---actual.pdf");
Files.write(outPdf.toPath(), actualPdfBytes);
}

if (problems.stream().anyMatch(p -> p.testImages != null)) {
System.err.println("For test case (" + resource + ") writing diff images to '" + outputPath + "'");
}

for (PdfCompareResult result : problems) {
if (result.testImages != null) {
File output = new File(outputPath, resource + "---" + result.pageNumber + "---diff.png");
ImageIO.write(result.testImages.createDiff(), "png", output);

output = new File(outputPath, resource + "---" + result.pageNumber + "---actual.png");
ImageIO.write(result.testImages.getActual(), "png", output);

output = new File(outputPath, resource + "---" + result.pageNumber + "---expected.png");
ImageIO.write(result.testImages.getExpected(), "png", output);
}
}

return problems.isEmpty();
}
}
Binary file not shown.
Original file line number Diff line number Diff line change
@@ -0,0 +1,33 @@
<html>
<head>
<style>
@page {
size: 300px 300px;
margin: 20px;
}
body {
margin: 5px;
padding: 10px;
}
</style>
</head>
<body>

<div>Page one</div>
This is a test!

<div style="position: fixed; left: 140px; top: 3cm;">Fixed layer</div>

<div style="page-break-before: always;">This is page two.</div>

<div style="position: absolute; left: 70px; top: 300px;">Absolute layer on page two</div>

<div style="page-break-before: always;">This is page three.</div>

<div style="position: relative; height: 50px;">
Relative
<div style="position: absolute; top: 25px; left: 5px;">Abs in rel</div>
</div>

</body>
</html>
Original file line number Diff line number Diff line change
Expand Up @@ -6,9 +6,11 @@
import static org.hamcrest.CoreMatchers.equalTo;
import static org.hamcrest.CoreMatchers.instanceOf;

import java.awt.Color;
import java.io.ByteArrayOutputStream;
import java.io.File;
import java.io.IOException;
import java.io.InputStream;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
Expand All @@ -24,6 +26,8 @@
import org.apache.pdfbox.io.IOUtils;
import org.apache.pdfbox.pdmodel.PDDocument;
import org.apache.pdfbox.pdmodel.PDDocumentInformation;
import org.apache.pdfbox.pdmodel.PDPageContentStream;
import org.apache.pdfbox.pdmodel.PDPageContentStream.AppendMode;
import org.apache.pdfbox.pdmodel.common.PDRectangle;
import org.apache.pdfbox.pdmodel.interactive.action.PDActionGoTo;
import org.apache.pdfbox.pdmodel.interactive.action.PDActionURI;
Expand All @@ -43,6 +47,8 @@
import org.junit.Test;

import com.openhtmltopdf.outputdevice.helper.ExternalResourceControlPriority;
import com.openhtmltopdf.pdfboxout.PagePosition;
import com.openhtmltopdf.pdfboxout.PdfBoxRenderer;
import com.openhtmltopdf.pdfboxout.PdfRendererBuilder;
import com.openhtmltopdf.testcases.TestcaseRunner;
import com.openhtmltopdf.util.Diagnostic;
Expand Down Expand Up @@ -71,20 +77,30 @@ private static void render(String fileName, String html, BuilderConfig config) t
System.err.println("Failed to render resource (" + fileName + ")");
e.printStackTrace();
}


writePdfToFile(fileName, actual);
}

private static void writePdfToFile(String fileName, ByteArrayOutputStream actual) throws IOException {
FileUtils.writeByteArrayToFile(new File(OUT_PATH, fileName + ".pdf"), actual.toByteArray());
}
private static PDDocument run(String fileName, BuilderConfig config) throws IOException {

private static String loadHtml(String fileName) throws IOException {
String absResPath = RES_PATH + fileName + ".html";

byte[] htmlBytes = IOUtils
.toByteArray(TestcaseRunner.class.getResourceAsStream(absResPath));

String html = new String(htmlBytes, Charsets.UTF_8);

try (InputStream is = TestcaseRunner.class.getResourceAsStream(absResPath)) {
byte[] htmlBytes = IOUtils
.toByteArray(is);

return new String(htmlBytes, Charsets.UTF_8);
}
}

private static PDDocument run(String fileName, BuilderConfig config) throws IOException {
String html = loadHtml(fileName);

render(fileName, html, config);

return load(fileName);
}

Expand Down Expand Up @@ -1093,6 +1109,65 @@ public void testIssue508FileEmbed() throws IOException {
}
}

/**
* Tests the PdfBoxRenderer::getPagePositions and
* PdfBoxRenderer::getLastYPositionOfContent apis.
* It does this by drawing a rect around each layer and comparing
* with the expected document.
*/
@Test
public void testIssue427GetBodyPagePositions() throws IOException {
String filename = "issue-427-body-page-positions";
String html = loadHtml(filename);
ByteArrayOutputStream os = new ByteArrayOutputStream();

PdfRendererBuilder builder = new PdfRendererBuilder();

builder.withHtmlContent(html, null);
builder.useFastMode();
builder.toStream(os);

float lastContentLine;

try (PdfBoxRenderer renderer = builder.buildPdfRenderer()) {
renderer.createPDFWithoutClosing();

List<PagePosition> posList = renderer.getPagePositions();
lastContentLine = renderer.getLastYPositionOfContent();

int i = -1;
PDPageContentStream stream = null;
for (PagePosition pos : posList) {
if (i != pos.getPageNo()) {
if (stream != null) {
stream.close();
}

stream = new PDPageContentStream(renderer.getPdfDocument(),
renderer.getPdfDocument().getPage(pos.getPageNo()), AppendMode.APPEND, false, false);
stream.setLineWidth(1f);
stream.setStrokingColor(Color.ORANGE);

i = pos.getPageNo();
}


stream.addRect(pos.getX(), pos.getY(), pos.getWidth(), pos.getHeight());
stream.stroke();
}

if (stream != null) {
stream.close();
}

renderer.getPdfDocument().save(os);
writePdfToFile(filename, os);
}

assertTrue(TestSupport.comparePdfs(os.toByteArray(), filename));
assertEquals(111.48, lastContentLine, 0.5);
}

// TODO:
// + More form controls.
// + Custom meta info.
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -74,4 +74,10 @@ public String getId() {
public void setId(String id) {
_id = id;
}

@Override
public String toString() {
return String.format("PagePosition [_id=%s, _pageNo=%s, _x=%s, _width=%s, _y=%s, _height=%s]",
_id, _pageNo, _x, _width, _y, _height);
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -53,8 +53,6 @@
import org.apache.pdfbox.pdmodel.PDPageContentStream;
import org.apache.pdfbox.pdmodel.font.PDFont;
import org.apache.pdfbox.pdmodel.graphics.form.PDFormXObject;
import org.apache.pdfbox.pdmodel.graphics.image.JPEGFactory;
import org.apache.pdfbox.pdmodel.graphics.image.LosslessFactory;
import org.apache.pdfbox.pdmodel.graphics.image.PDImageXObject;
import org.apache.pdfbox.pdmodel.graphics.shading.PDShading;
import org.apache.pdfbox.pdmodel.graphics.state.RenderingMode;
Expand Down
Loading

0 comments on commit 214a21a

Please sign in to comment.