Author: tilman
Date: Sun Jul  5 09:06:59 2026
New Revision: 1935904

Log:
PDFBOX-4951: add rendering test, refactor

Added:
   
pdfbox/trunk/pdfbox-layout-awt/src/test/java/org/apache/pdfbox/glyphlayout/TestBase.java
   (contents, props changed)
Modified:
   
pdfbox/trunk/pdfbox-layout-awt/src/test/java/org/apache/pdfbox/glyphlayout/GlyphLayoutBidiTest.java
   
pdfbox/trunk/pdfbox-layout-awt/src/test/java/org/apache/pdfbox/glyphlayout/GlyphLayoutDin91379FormTest.java
   
pdfbox/trunk/pdfbox-layout-awt/src/test/java/org/apache/pdfbox/glyphlayout/GlyphLayoutDin91379Test.java
   
pdfbox/trunk/pdfbox-layout-awt/src/test/java/org/apache/pdfbox/glyphlayout/GlyphLayoutLigaturesAndKerningTest.java

Modified: 
pdfbox/trunk/pdfbox-layout-awt/src/test/java/org/apache/pdfbox/glyphlayout/GlyphLayoutBidiTest.java
==============================================================================
--- 
pdfbox/trunk/pdfbox-layout-awt/src/test/java/org/apache/pdfbox/glyphlayout/GlyphLayoutBidiTest.java
 Sun Jul  5 08:30:13 2026        (r1935903)
+++ 
pdfbox/trunk/pdfbox-layout-awt/src/test/java/org/apache/pdfbox/glyphlayout/GlyphLayoutBidiTest.java
 Sun Jul  5 09:06:59 2026        (r1935904)
@@ -19,13 +19,9 @@ package org.apache.pdfbox.glyphlayout;
 import org.junit.jupiter.api.Test;
 
 import java.awt.FontFormatException;
-import java.io.File;
 import java.io.IOException;
-import java.io.InputStream;
+import java.net.URISyntaxException;
 
-import static org.junit.jupiter.api.Assertions.assertEquals;
-
-import org.apache.pdfbox.Loader;
 import org.apache.pdfbox.pdmodel.PDDocument;
 import org.apache.pdfbox.pdmodel.PDPage;
 import org.apache.pdfbox.pdmodel.PDPageContentStream;
@@ -36,7 +32,7 @@ import org.apache.pdfbox.pdmodel.font.PD
  *
  * @author Volker Kunert
  */
-public class GlyphLayoutBidiTest
+public class GlyphLayoutBidiTest extends TestBase
 {
     public static final String TEXT1 = "نحن الآن في شهر رمضان 1447 هجري";
     public static final String TEXT2 = "Guten Tag ";
@@ -78,11 +74,12 @@ public class GlyphLayoutBidiTest
     }
 
     @Test
-    void testGlyphLayoutBidi() throws IOException, FontFormatException
+    void testGlyphLayoutBidi() throws IOException, FontFormatException, 
URISyntaxException
     {
         GlyphLayoutProcessorAwt glyphLayoutProcessorAwt = new 
GlyphLayoutProcessorAwt();
 
-        String outputFilename = "target/GlyphLayoutBidi.pdf";
+        String outputName = "GlyphLayoutBidi.pdf";
+        String outputFilename = "target/" + outputName;
         String arabicPath = "/ttf/NotoSansArabic-Regular.ttf";
         String lgcPath = "/ttf/DejaVuSans.ttf";
 
@@ -107,20 +104,6 @@ public class GlyphLayoutBidiTest
             }
             doc.save(outputFilename);
         }
-        //TODO add rendering comparison
-        try (PDDocument doc = Loader.loadPDF(new File(outputFilename)))
-        {
-            assertEquals(1, doc.getNumberOfPages());
-        }
-    }
-
-    /*
-     * Create the PDType0Font font
-     */
-    private PDType0Font createPdType0Font(GlyphLayoutProcessorAwt 
glyphLayoutProcessorAwt, PDDocument doc,
-            String fontPath) throws IOException, FontFormatException
-    {
-        InputStream fontStream = this.getClass().getResourceAsStream(fontPath);
-        return glyphLayoutProcessorAwt.loadFont(doc, fontStream);
+        checkRenderIdent(outputName);
     }
 }

Modified: 
pdfbox/trunk/pdfbox-layout-awt/src/test/java/org/apache/pdfbox/glyphlayout/GlyphLayoutDin91379FormTest.java
==============================================================================
--- 
pdfbox/trunk/pdfbox-layout-awt/src/test/java/org/apache/pdfbox/glyphlayout/GlyphLayoutDin91379FormTest.java
 Sun Jul  5 08:30:13 2026        (r1935903)
+++ 
pdfbox/trunk/pdfbox-layout-awt/src/test/java/org/apache/pdfbox/glyphlayout/GlyphLayoutDin91379FormTest.java
 Sun Jul  5 09:06:59 2026        (r1935904)
@@ -29,7 +29,6 @@ import org.apache.pdfbox.pdmodel.font.PD
 import org.apache.pdfbox.pdmodel.interactive.form.PDAcroForm;
 import org.apache.pdfbox.pdmodel.interactive.form.PDField;
 import org.apache.pdfbox.pdmodel.interactive.form.PDTextField;
-import static org.junit.jupiter.api.Assertions.assertEquals;
 import org.junit.jupiter.api.Test;
 
 /*
@@ -42,7 +41,7 @@ import org.junit.jupiter.api.Test;
  * @author Volker Kunert
  */
 
-class GlyphLayoutDin91379FormTest
+class GlyphLayoutDin91379FormTest extends TestBase
 {
     static String LATIN_CHARS_DIN_91379 =
                     "DIN 91379: Characters in Unicode for the electronic 
processing of names "
@@ -91,7 +90,8 @@ class GlyphLayoutDin91379FormTest
     {
         GlyphLayoutProcessorAwt glyphLayoutProcessor = new 
GlyphLayoutProcessorAwt();
 
-        String outputFilename = "target/GlyphLayoutDIN91379Form.pdf";
+        String outputName = "GlyphLayoutDIN91379Form.pdf";
+        String outputFilename = "target/" + outputName;
 
         String fontSizeString = "12";
 
@@ -127,11 +127,6 @@ class GlyphLayoutDin91379FormTest
             acroForm.flatten();
             doc.save(outputFilename);
         }
-
-        //TODO add rendering comparison
-        try (PDDocument doc = Loader.loadPDF(new File(outputFilename)))
-        {
-            assertEquals(1, doc.getNumberOfPages());
-        }
+        checkRenderIdent(outputName);
     }
 }

Modified: 
pdfbox/trunk/pdfbox-layout-awt/src/test/java/org/apache/pdfbox/glyphlayout/GlyphLayoutDin91379Test.java
==============================================================================
--- 
pdfbox/trunk/pdfbox-layout-awt/src/test/java/org/apache/pdfbox/glyphlayout/GlyphLayoutDin91379Test.java
     Sun Jul  5 08:30:13 2026        (r1935903)
+++ 
pdfbox/trunk/pdfbox-layout-awt/src/test/java/org/apache/pdfbox/glyphlayout/GlyphLayoutDin91379Test.java
     Sun Jul  5 09:06:59 2026        (r1935904)
@@ -25,6 +25,7 @@ import java.io.InputStream;
 import java.io.OutputStream;
 import java.io.OutputStreamWriter;
 import java.io.Writer;
+import java.net.URISyntaxException;
 import org.apache.pdfbox.Loader;
 
 import org.junit.jupiter.api.Test;
@@ -44,7 +45,7 @@ import static org.junit.jupiter.api.Asse
  *
  * @author Volker Kunert
  */
-class GlyphLayoutDin91379Test
+class GlyphLayoutDin91379Test extends TestBase
 {
     static String LATIN_CHARS_DIN_91379 =
                     "DIN 91379: Characters in Unicode for the electronic 
processing of names \n"
@@ -91,11 +92,12 @@ class GlyphLayoutDin91379Test
                     + "Additional non-letters (not included in DIN 91379): – — 
•�";
 
     @Test
-    void testGlyphLayoutDin91379() throws IOException, FontFormatException
+    void testGlyphLayoutDin91379() throws IOException, FontFormatException, 
URISyntaxException
     {
         GlyphLayoutProcessorAwt glyphLayoutProcessor = new 
GlyphLayoutProcessorAwt();
 
-        String outputPDFFilename = "target/GlyphLayoutDIN91379.pdf";
+        String outputName = "GlyphLayoutDIN91379.pdf";
+        String outputPDFFilename = "target/" + outputName;
         String outputTextFilename = "target/GlyphLayoutDIN91379.txt";
         float fontSize = 12.0f;
 
@@ -117,8 +119,8 @@ class GlyphLayoutDin91379Test
             }
             doc.save(outputPDFFilename);
         }
+        checkRenderIdent(outputName);
         
-        //TODO add rendering comparison
         try (PDDocument doc = Loader.loadPDF(new File(outputPDFFilename)))
         {
             assertEquals(1, doc.getNumberOfPages());
@@ -160,17 +162,4 @@ class GlyphLayoutDin91379Test
             }
         }
     }
-
-    /*
-     * show one line
-     */
-    private void showCompositesLine(PDPageContentStream cs, PDType0Font font, 
float fontSize,
-            float x, float y, String line) throws IOException
-    {
-        cs.beginText();
-        cs.setFont(font, fontSize);
-        cs.newLineAtOffset(x, y);
-        cs.showText(line);
-        cs.endText();
-    }
 }

Modified: 
pdfbox/trunk/pdfbox-layout-awt/src/test/java/org/apache/pdfbox/glyphlayout/GlyphLayoutLigaturesAndKerningTest.java
==============================================================================
--- 
pdfbox/trunk/pdfbox-layout-awt/src/test/java/org/apache/pdfbox/glyphlayout/GlyphLayoutLigaturesAndKerningTest.java
  Sun Jul  5 08:30:13 2026        (r1935903)
+++ 
pdfbox/trunk/pdfbox-layout-awt/src/test/java/org/apache/pdfbox/glyphlayout/GlyphLayoutLigaturesAndKerningTest.java
  Sun Jul  5 09:06:59 2026        (r1935904)
@@ -28,10 +28,8 @@ package org.apache.pdfbox.glyphlayout;
  */
 
 import java.awt.FontFormatException;
-import java.io.File;
 import java.io.IOException;
-import java.io.InputStream;
-import org.apache.pdfbox.Loader;
+import java.net.URISyntaxException;
 
 import static org.junit.jupiter.api.Assertions.assertEquals;
 import static org.junit.jupiter.api.Assertions.assertThrows;
@@ -42,7 +40,7 @@ import org.apache.pdfbox.pdmodel.PDPage;
 import org.apache.pdfbox.pdmodel.PDPageContentStream;
 import org.apache.pdfbox.pdmodel.font.PDType0Font;
 
-class GlyphLayoutLigaturesAndKerningTest
+class GlyphLayoutLigaturesAndKerningTest extends TestBase
 {
     static final String FIRACODE_STRING = "!= == === >= <=";
     static final String DEJAVU_STRING =  "AVATAR, effective, affiliation, 
float, film, affluent";
@@ -67,27 +65,31 @@ class GlyphLayoutLigaturesAndKerningTest
 
         try (PDDocument doc = new PDDocument())
         {
-            PDType0Font lohitBengaliFont = 
createPdType0Font(glyphLayoutProcessor, doc, lohitBengaliPath);
+            PDType0Font lohitBengaliFont = 
createPdType0Font(glyphLayoutProcessor, doc, lohitBengaliPath, 
+                            new GlyphLayoutFontLoaderAwt.FontOptions());
 
             PDPage page = new PDPage();
             doc.addPage(page);
             try (PDPageContentStream cs = new PDPageContentStream(doc, page))
             {
                 cs.setGlyphLayoutProcessor(glyphLayoutProcessor);
-                
+
                 IllegalArgumentException ex = 
assertThrows(IllegalArgumentException.class, () -> 
                         showComposites(cs, lohitBengaliFont, 1, 0, 0, 
"123ABC"));
                 assertEquals("Missing glyph in font 'Lohit Bengali' for the 
character 'A', codePoint: 65 (U+0041).", ex.getMessage());
+
+                // Ignore the "You did not call endText()" warning, this is 
because of the premature close
             }
         }
     }
   
     @Test
-    void testLigaturesAndKerning() throws IOException, FontFormatException
+    void testLigaturesAndKerning() throws IOException, FontFormatException, 
URISyntaxException
     {
         GlyphLayoutProcessorAwt glyphLayoutProcessor = new 
GlyphLayoutProcessorAwt();
 
-        String outputFilename = "target/GlyphLayoutLigaturesAndKerning.pdf";
+        String outputName = "GlyphLayoutLigaturesAndKerning.pdf";
+        String outputFilename = "target/" + outputName;
         String firaPath = "/ttf/FiraCode-Regular.ttf";
         String dejavuPath = "/ttf/DejaVuSans.ttf"; // ligatures not in 
Liberation nor in Arimo
         String lohitBengaliPath = "/ttf/Lohit-Bengali.ttf";
@@ -133,39 +135,13 @@ class GlyphLayoutLigaturesAndKerningTest
             }
             doc.save(outputFilename);
         }
-        //TODO add rendering comparison
-        try (PDDocument doc = Loader.loadPDF(new File(outputFilename)))
-        {
-            assertEquals(1, doc.getNumberOfPages());
-        }
-    }
-
-    /*
-     * Create the PDType0Font font
-     */
-    private PDType0Font createPdType0Font(GlyphLayoutProcessorAwt 
glyphLayoutProcessor, PDDocument pdDocument,
-            String fontPath) throws IOException, FontFormatException
-    {
-        InputStream fontStream = this.getClass().
-                getResourceAsStream(fontPath);
-        return glyphLayoutProcessor.loadFont(pdDocument, fontStream);
+        checkRenderIdent(outputName);
     }
 
-    /*
-     * Create the PDType0Font font with font options
-     */
-    private PDType0Font createPdType0Font(GlyphLayoutProcessorAwt 
glyphLayoutProcessor, PDDocument pdDocument,
-            String fontPath, GlyphLayoutFontLoaderAwt.FontOptions fontOptions) 
throws IOException, FontFormatException
-    {
-        InputStream fontStream = this.getClass().
-                getResourceAsStream(fontPath);
-        return glyphLayoutProcessor.loadFont(pdDocument, fontStream, 
fontOptions);
-    }
-
-    /*
+    /**
      * break the text into lines and show them
      */
-    public static float showComposites(PDPageContentStream cs, PDType0Font 
font, float fontSize,
+    private float showComposites(PDPageContentStream cs, PDType0Font font, 
float fontSize,
             float x, float y, String s) throws IOException
     {
 
@@ -184,17 +160,4 @@ class GlyphLayoutLigaturesAndKerningTest
         }
         return y;
     }
-
-    /*
-     * show one line
-     */
-    public static void showCompositesLine(PDPageContentStream cs, PDType0Font 
font, float fontSize,
-            float x, float y, String line) throws IOException
-    {
-        cs.beginText();
-        cs.setFont(font, fontSize);
-        cs.newLineAtOffset(x, y);
-        cs.showText(line);
-        cs.endText();
-    }
 }

Added: 
pdfbox/trunk/pdfbox-layout-awt/src/test/java/org/apache/pdfbox/glyphlayout/TestBase.java
==============================================================================
--- /dev/null   00:00:00 1970   (empty, because file is newly added)
+++ 
pdfbox/trunk/pdfbox-layout-awt/src/test/java/org/apache/pdfbox/glyphlayout/TestBase.java
    Sun Jul  5 09:06:59 2026        (r1935904)
@@ -0,0 +1,108 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.pdfbox.glyphlayout;
+
+import java.awt.FontFormatException;
+import java.awt.image.BufferedImage;
+import java.io.File;
+import java.io.IOException;
+import java.io.InputStream;
+import java.net.URISyntaxException;
+import org.apache.pdfbox.Loader;
+import org.apache.pdfbox.pdmodel.PDDocument;
+import org.apache.pdfbox.pdmodel.PDPageContentStream;
+import org.apache.pdfbox.pdmodel.font.PDType0Font;
+import org.apache.pdfbox.rendering.PDFRenderer;
+import static org.junit.jupiter.api.Assertions.assertEquals;
+import static org.junit.jupiter.api.Assertions.fail;
+
+/**
+ *
+ * @author Tilman Hausherr
+ * @author Volker Kunert
+ */
+class TestBase
+{
+    void checkRenderIdent(String outputName) throws IOException, 
URISyntaxException
+    {
+        BufferedImage expectedImage;
+        BufferedImage actualImage;
+        try (PDDocument doc = Loader.loadPDF(new File("target/" + outputName)))
+        {
+            PDFRenderer r = new PDFRenderer(doc);
+            expectedImage = r.renderImage(0);
+        }
+        try (PDDocument doc = Loader.loadPDF(new 
File(TestBase.class.getResource("/pdf/" + outputName).toURI())))
+        {
+            PDFRenderer r = new PDFRenderer(doc);
+            actualImage = r.renderImage(0);
+        }
+
+        int w = expectedImage.getWidth();
+        int h = expectedImage.getHeight();
+        assertEquals(w, actualImage.getWidth());
+        assertEquals(h, actualImage.getHeight());
+        for (int y = 0; y < h; ++y)
+        {
+            for (int x = 0; x < w; ++x)
+            {
+                int p1 = expectedImage.getRGB(x, y);
+                int p2 = actualImage.getRGB(x, y);
+                if (p1 != p2)
+                {
+                    String errMsg = String.format("(%d,%d) expected: <%08X> 
but was: <%08X>; ", 
+                            x, y, p1, p2);
+                    fail(errMsg);
+                }
+            }
+        }
+    }
+
+    /**
+     * Create the PDType0Font font
+     */
+    PDType0Font createPdType0Font(GlyphLayoutProcessorAwt 
glyphLayoutProcessor, PDDocument doc,
+            String fontPath) throws IOException, FontFormatException
+    {
+        return createPdType0Font(glyphLayoutProcessor, doc, fontPath, new 
GlyphLayoutFontLoaderAwt.FontOptions());
+    }
+
+    /*
+     * Create the PDType0Font font with font options
+     */
+    PDType0Font createPdType0Font(GlyphLayoutProcessorAwt 
glyphLayoutProcessor, PDDocument doc,
+            String fontPath, GlyphLayoutFontLoaderAwt.FontOptions fontOptions) 
throws IOException, FontFormatException
+    {
+        try (InputStream fontStream = 
this.getClass().getResourceAsStream(fontPath))
+        {
+            return glyphLayoutProcessor.loadFont(doc, fontStream, fontOptions);
+        }
+    }
+
+    /*
+     * show one line
+     */
+    void showCompositesLine(PDPageContentStream cs, PDType0Font font, float 
fontSize,
+            float x, float y, String line) throws IOException
+    {
+        cs.beginText();
+        cs.setFont(font, fontSize);
+        cs.newLineAtOffset(x, y);
+        cs.showText(line);
+        cs.endText();
+    }
+}

Reply via email to