Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

#427 API for getting the last y position and more #666

Merged
merged 4 commits into from
Mar 19, 2021
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
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 @@ -42,7 +46,10 @@
import org.junit.Assert;
import org.junit.Test;

import com.openhtmltopdf.layout.Layer;
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 +78,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 +1110,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<Layer>> posList = renderer.getLayersPositions();
lastContentLine = renderer.getLastContentBottom();

int i = -1;
PDPageContentStream stream = null;
for (PagePosition<Layer> 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 @@ -19,59 +19,57 @@
*/
package com.openhtmltopdf.pdfboxout;

public class PagePosition {
private String _id;
private int _pageNo;
private float _x;
private float _width;
private float _y;
private float _height;

public class PagePosition<T> {
private final String _id;
private final T _element;
private final int _pageNo;
private final float _x;
private final float _y;
private final float _width;
private final float _height;

public PagePosition(String id, T element, int pageNo, float x, float y, float width, float height) {
this._id = id;
this._element = element;
this._pageNo = pageNo;
this._x = x;
this._y = y;
this._width = width;
this._height = height;
}

public int getPageNo() {
return _pageNo;
}

public void setPageNo(int pageNo) {
_pageNo = pageNo;
}


public float getX() {
return _x;
}

public void setX(float x) {
_x = x;
}

public float getWidth() {
return _width;
}

public void setWidth(float width) {
_width = width;
}


public float getY() {
return _y;
}
public void setY(float y) {
_y = y;

public float getWidth() {
return _width;
}

public float getHeight() {
return _height;
}

public void setHeight(float height) {
_height = height;
}

public String getId() {
return _id;
}

public void setId(String id) {
_id = id;
public T getElement() {
return _element;
}

@Override
public String toString() {
return String.format(
"PagePosition [_id=%s, _element=%s, _pageNo=%s, _x=%s, _y=%s, _width=%s, _height=%s]",
_id, _element, _pageNo, _x, _y, _width, _height);
}
}
Loading