diff --git a/openhtmltopdf-examples/src/main/java/com/openhtmltopdf/visualtest/TestSupport.java b/openhtmltopdf-examples/src/main/java/com/openhtmltopdf/visualtest/TestSupport.java index 5a5961b8c..df41597f2 100644 --- a/openhtmltopdf-examples/src/main/java/com/openhtmltopdf/visualtest/TestSupport.java +++ b/openhtmltopdf-examples/src/main/java/com/openhtmltopdf/visualtest/TestSupport.java @@ -46,6 +46,8 @@ import com.openhtmltopdf.visualtest.VisualTester.BuilderConfig; public class TestSupport { + public static final String FONT_FILES_PATH = "target/test/visual-tests/"; + /** * Output the font file as a regular file so we don't have to use streams. * @throws IOException @@ -54,15 +56,28 @@ public static void makeFontFile(String resource) throws IOException { File outputDirectory = new File("target/test/visual-tests/test-output/j2d/"); outputDirectory.mkdirs(); - File fontFile = new File("target/test/visual-tests/" + resource); - + File fontFile = new File(FONT_FILES_PATH + resource); + if (!fontFile.exists()) { try (InputStream in = TestSupport.class.getResourceAsStream("/visualtest/html/fonts/" + resource)) { Files.copy(in, fontFile.toPath()); } } } - + + public static File fontFileKarlaBold() { + return new File(FONT_FILES_PATH + "Karla-Bold.ttf"); + } + + public static File fontFileNotoNaskhArabicRegular() { + return new File(FONT_FILES_PATH + "NotoNaskhArabic-Regular.ttf"); + } + + public static File fontFileSourceSansProRegular() { + return new File(FONT_FILES_PATH + "SourceSansPro-Regular.ttf"); + } + + /** * Output the test fonts from classpath to files in target so we can use them * without streams. @@ -153,25 +168,25 @@ public void setText(String newText) { this.matcher = SPACES.matcher(newText); } } - + public static final BuilderConfig WITH_FONT = (builder) -> { - builder.useFont(new File("target/test/visual-tests/Karla-Bold.ttf"), "TestFont"); + builder.useFont(fontFileKarlaBold(), "TestFont"); builder.useUnicodeLineBreaker(new SimpleTextBreaker()); }; - + public static final Java2DBuilderConfig J2D_WITH_FONT = (builder) -> { - builder.useFont(new File("target/test/visual-tests/Karla-Bold.ttf"), "TestFont"); + builder.useFont(fontFileKarlaBold(), "TestFont"); builder.useUnicodeLineBreaker(new SimpleTextBreaker()); }; - + public static final BuilderConfig WITH_EXTRA_FONT = (builder) -> { WITH_FONT.configure(builder); - builder.useFont(new File("target/test/visual-tests/SourceSansPro-Regular.ttf"), "ExtraFont"); + builder.useFont(fontFileSourceSansProRegular(), "ExtraFont"); }; public static final BuilderConfig WITH_ARABIC = (builder) -> { WITH_FONT.configure(builder); - builder.useFont(new File("target/test/visual-tests/NotoNaskhArabic-Regular.ttf"), "arabic"); + builder.useFont(fontFileNotoNaskhArabicRegular(), "arabic"); builder.useUnicodeBidiSplitter(new ICUBidiSplitter.ICUBidiSplitterFactory()); builder.useUnicodeBidiReorderer(new ICUBidiReorderer()); builder.useUnicodeLineBreaker(new ICUBreakers.ICULineBreaker(Locale.US)); // Overrides WITH_FONT diff --git a/openhtmltopdf-examples/src/main/resources/visualtest/html/pr-684-font-reuse-1.html b/openhtmltopdf-examples/src/main/resources/visualtest/html/pr-684-font-reuse-1.html new file mode 100644 index 000000000..6121600a8 --- /dev/null +++ b/openhtmltopdf-examples/src/main/resources/visualtest/html/pr-684-font-reuse-1.html @@ -0,0 +1,5 @@ + + + This first document should use the same font resource as the second document. + + diff --git a/openhtmltopdf-examples/src/main/resources/visualtest/html/pr-684-font-reuse-2.html b/openhtmltopdf-examples/src/main/resources/visualtest/html/pr-684-font-reuse-2.html new file mode 100644 index 000000000..77689aadf --- /dev/null +++ b/openhtmltopdf-examples/src/main/resources/visualtest/html/pr-684-font-reuse-2.html @@ -0,0 +1,5 @@ + + + This second document should use the same font resource as the first document. + + diff --git a/openhtmltopdf-examples/src/test/java/com/openhtmltopdf/nonvisualregressiontests/NonVisualRegressionTest.java b/openhtmltopdf-examples/src/test/java/com/openhtmltopdf/nonvisualregressiontests/NonVisualRegressionTest.java index 662e9548b..37f02958f 100644 --- a/openhtmltopdf-examples/src/test/java/com/openhtmltopdf/nonvisualregressiontests/NonVisualRegressionTest.java +++ b/openhtmltopdf-examples/src/test/java/com/openhtmltopdf/nonvisualregressiontests/NonVisualRegressionTest.java @@ -24,12 +24,15 @@ import org.apache.pdfbox.cos.COSDocument; import org.apache.pdfbox.cos.COSName; import org.apache.pdfbox.cos.COSObject; +import org.apache.pdfbox.cos.COSObjectKey; 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.font.PDFont; +import org.apache.pdfbox.pdmodel.font.PDType0Font; import org.apache.pdfbox.pdmodel.interactive.action.PDActionGoTo; import org.apache.pdfbox.pdmodel.interactive.action.PDActionURI; import org.apache.pdfbox.pdmodel.interactive.annotation.PDAnnotationFileAttachment; @@ -44,10 +47,12 @@ import org.apache.pdfbox.text.PDFTextStripper; import org.hamcrest.CustomTypeSafeMatcher; import org.junit.Assert; +import org.junit.BeforeClass; import org.junit.Test; import com.openhtmltopdf.layout.Layer; import com.openhtmltopdf.outputdevice.helper.ExternalResourceControlPriority; +import com.openhtmltopdf.pdfboxout.PDFontSupplier; import com.openhtmltopdf.pdfboxout.PagePosition; import com.openhtmltopdf.pdfboxout.PdfBoxRenderer; import com.openhtmltopdf.pdfboxout.PdfRendererBuilder; @@ -61,7 +66,12 @@ public class NonVisualRegressionTest { private static final String RES_PATH = "/visualtest/html/"; private static final String OUT_PATH = "target/test/visual-tests/test-output/"; - + + @BeforeClass + public static void configureTests() throws IOException { + TestSupport.makeFontFiles(); + } + private static void render(String fileName, String html, BuilderConfig config) throws IOException { ByteArrayOutputStream actual = new ByteArrayOutputStream(); @@ -1169,6 +1179,56 @@ public void testIssue427GetBodyPagePositions() throws IOException { assertEquals(111.48, lastContentLine, 0.5); } + /** + * Tests that it is possible to use a PDDocument multiple times + * without re-embedding required fonts. + * PR#684, Issue#683 + */ + @Test + public void testPr684FontReuse() throws IOException { + String html1 = loadHtml("pr-684-font-reuse-1"); + String html2 = loadHtml("pr-684-font-reuse-2"); + + try (PDDocument doc = new PDDocument()) { + PDFont font = PDType0Font.load(doc, TestSupport.fontFileKarlaBold()); + PDFontSupplier supplier = new PDFontSupplier(font); + + try (PdfBoxRenderer renderer = new PdfRendererBuilder() + .usePDDocument(doc) + .withHtmlContent(html1, null) + .useFont(supplier, "MyFont") + .buildPdfRenderer()) { + renderer.createPDFWithoutClosing(); + } + + try (PdfBoxRenderer renderer = new PdfRendererBuilder() + .usePDDocument(doc) + .withHtmlContent(html2, null) + .useFont(supplier, "MyFont") + .buildPdfRenderer()) { + renderer.createPDFWithoutClosing(); + } + + ByteArrayOutputStream os = new ByteArrayOutputStream(); + doc.save(os); + writePdfToFile("pr-684-font-reuse", os); + } + + try (PDDocument doc = load("pr-684-font-reuse")) { + try (COSDocument cos = doc.getDocument()) { + COSName name1 = doc.getPage(0).getResources().getFontNames().iterator().next(); + COSName name2 = doc.getPage(1).getResources().getFontNames().iterator().next(); + + COSObjectKey fnt1 = cos.getKey(doc.getPage(0).getResources().getFont(name1).getCOSObject()); + COSObjectKey fnt2 = cos.getKey(doc.getPage(1).getResources().getFont(name2).getCOSObject()); + + assertEquals(fnt1, fnt2); + } + + remove("pr-684-font-reuse", doc); + } + } + // TODO: // + More form controls. // + Custom meta info.