You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@pdfbox.apache.org by ti...@apache.org on 2023/11/18 11:53:43 UTC

svn commit: r1913915 - /pdfbox/trunk/fontbox/src/main/java/org/apache/fontbox/pfb/PfbParser.java

Author: tilman
Date: Sat Nov 18 11:53:43 2023
New Revision: 1913915

URL: http://svn.apache.org/viewvc?rev=1913915&view=rev
Log:
PDFBOX-5713: rewritten parser to accept more than 3 segments and rearrange them as ASCII-BINARY-ASCII, as described in "3.3 IBM PC Format" of Adobe Technical Note #5040

Modified:
    pdfbox/trunk/fontbox/src/main/java/org/apache/fontbox/pfb/PfbParser.java

Modified: pdfbox/trunk/fontbox/src/main/java/org/apache/fontbox/pfb/PfbParser.java
URL: http://svn.apache.org/viewvc/pdfbox/trunk/fontbox/src/main/java/org/apache/fontbox/pfb/PfbParser.java?rev=1913915&r1=1913914&r2=1913915&view=diff
==============================================================================
--- pdfbox/trunk/fontbox/src/main/java/org/apache/fontbox/pfb/PfbParser.java (original)
+++ pdfbox/trunk/fontbox/src/main/java/org/apache/fontbox/pfb/PfbParser.java Sat Nov 18 11:53:43 2023
@@ -22,7 +22,11 @@ import java.io.IOException;
 import java.io.InputStream;
 import java.nio.file.Files;
 import java.nio.file.Paths;
+import java.util.ArrayList;
 import java.util.Arrays;
+import java.util.List;
+import org.apache.logging.log4j.LogManager;
+import org.apache.logging.log4j.Logger;
 
 /**
  * Parser for a pfb-file.
@@ -32,6 +36,8 @@ import java.util.Arrays;
  */
 public class PfbParser 
 {
+    private static final Logger LOG = LogManager.getLogger(PfbParser.class);
+    
     /**
      * the pfb header length.
      * (start-marker (1 byte), ascii-/binary-marker (1 byte), size (4 byte))
@@ -55,9 +61,9 @@ public class PfbParser
     private static final int BINARY_MARKER = 0x02;
 
     /**
-     * The record types in the pfb-file.
+     * the EOF marker.
      */
-    private static final int[] PFB_RECORDS = {ASCII_MARKER, BINARY_MARKER, ASCII_MARKER};
+    private static final int EOF_MARKER = 0x03;
 
     /**
      * the parsed pfb-data.
@@ -65,9 +71,9 @@ public class PfbParser
     private byte[] pfbdata;
 
     /**
-     * the lengths of the records.
+     * the lengths of the records (ASCII, BINARY, ASCII)
      */
-    private int[] lengths;
+    private final int[] lengths = new int[3];
 
     // sample (pfb-file)
     // 00000000 80 01 8b 15  00 00 25 21  50 53 2d 41  64 6f 62 65  
@@ -116,43 +122,87 @@ public class PfbParser
         {
             throw new IOException("PFB header missing");
         }
+        // read into segments and keep them
+        List<Integer> typeList = new ArrayList<>(3);
+        List<byte[]> barrList = new ArrayList<>();
         ByteArrayInputStream in = new ByteArrayInputStream(pfb);
-        pfbdata = new byte[pfb.length - PFB_HEADER_LENGTH];
-        lengths = new int[PFB_RECORDS.length];
-        int pointer = 0;
-        for (int records = 0; records < PFB_RECORDS.length; records++) 
+        int total = 0;
+        do
         {
             if (in.read() != START_MARKER) 
             {
                 throw new IOException("Start marker missing");
             }
-
-            if (in.read() != PFB_RECORDS[records]) 
+            int recordType = in.read();
+            if (recordType == EOF_MARKER)
+            {
+                break;
+            }
+            if (recordType != ASCII_MARKER && recordType != BINARY_MARKER)
             {
-                throw new IOException("Incorrect record type");
+                throw new IOException("Incorrect record type: " + recordType);
             }
 
             int size = in.read();
             size += in.read() << 8;
             size += in.read() << 16;
             size += in.read() << 24;
-            lengths[records] = size;
-            if (pointer >= pfbdata.length)
+            LOG.debug("record type: " + recordType + ", segment size: " + size);
+            byte ar[] = new byte[size];
+            int got = in.read(ar);
+            if (got != size)
             {
-                throw new EOFException("attempted to read past EOF");
+                throw new EOFException("EOF while reading PFB font");
             }
-            if (size > pfbdata.length - pointer)
+            total += size;
+            typeList.add(recordType);
+            barrList.add(ar);
+        }
+        while (true);
+        
+        // We now have ASCII and binary segments. Lets arrange these so that the ASCII segments
+        // come first, then the binary segments, then the last ASCII segment if it is
+        // 0000... cleartomark
+        
+        pfbdata = new byte[total];
+        byte[] cleartomarkSegment = null;
+        int dstPos = 0;
+        
+        // copy the ASCII segments
+        for (int i = 0; i < typeList.size(); ++i)
+        {
+            if (typeList.get(i) != ASCII_MARKER)
             {
-                throw new EOFException("attempted to read " + size + " bytes at position " + pointer +
-                        " into array of size " + pfbdata.length + ", but only space for " + 
-                        (pfbdata.length - pointer) + " bytes left");
+                continue;
             }
-            int got = in.read(pfbdata, pointer, size);
-            if (got < 0) 
+            byte[] ar = barrList.get(i);
+            if (i == typeList.size() - 1 && ar.length < 600 && new String(ar).contains("cleartomark"))
             {
-                throw new EOFException();
+                cleartomarkSegment = ar;
+                continue;
             }
-            pointer += got;
+            System.arraycopy(ar, 0, pfbdata, dstPos, ar.length);
+            dstPos += ar.length;
+        }
+        lengths[0] = dstPos;
+
+        // copy the binary segments
+        for (int i = 0; i < typeList.size(); ++i)
+        {
+            if (typeList.get(i) != BINARY_MARKER)
+            {
+                continue;
+            }
+            byte[] ar = barrList.get(i);
+            System.arraycopy(ar, 0, pfbdata, dstPos, ar.length);
+            dstPos += ar.length;
+        }
+        lengths[1] = dstPos - lengths[0];
+        
+        if (cleartomarkSegment != null)
+        {
+            System.arraycopy(cleartomarkSegment, 0, pfbdata, dstPos, cleartomarkSegment.length);
+            lengths[2] = cleartomarkSegment.length;
         }
     }