You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@pdfbox.apache.org by le...@apache.org on 2022/05/14 16:21:06 UTC

svn commit: r1900888 - in /pdfbox/trunk: fontbox/src/main/java/org/apache/fontbox/cff/ fontbox/src/test/java/org/apache/fontbox/cff/ pdfbox/src/main/java/org/apache/pdfbox/pdmodel/font/

Author: lehmi
Date: Sat May 14 16:21:06 2022
New Revision: 1900888

URL: http://svn.apache.org/viewvc?rev=1900888&view=rev
Log:
PDFBOX-5143: use RandomAccessRead to read a CFF font

Added:
    pdfbox/trunk/fontbox/src/main/java/org/apache/fontbox/cff/DataInputByteArray.java   (with props)
    pdfbox/trunk/fontbox/src/main/java/org/apache/fontbox/cff/DataInputRandomAccessRead.java   (with props)
    pdfbox/trunk/fontbox/src/test/java/org/apache/fontbox/cff/DataInputRandomAccessTest.java   (with props)
Removed:
    pdfbox/trunk/fontbox/src/main/java/org/apache/fontbox/cff/CFFDataInput.java
Modified:
    pdfbox/trunk/fontbox/src/main/java/org/apache/fontbox/cff/CFFParser.java
    pdfbox/trunk/fontbox/src/main/java/org/apache/fontbox/cff/DataInput.java
    pdfbox/trunk/fontbox/src/main/java/org/apache/fontbox/cff/Type1CharStringParser.java
    pdfbox/trunk/fontbox/src/main/java/org/apache/fontbox/cff/Type2CharStringParser.java
    pdfbox/trunk/fontbox/src/test/java/org/apache/fontbox/cff/CFFParserTest.java
    pdfbox/trunk/fontbox/src/test/java/org/apache/fontbox/cff/DataInputTest.java
    pdfbox/trunk/pdfbox/src/main/java/org/apache/pdfbox/pdmodel/font/PDCIDFontType0.java
    pdfbox/trunk/pdfbox/src/main/java/org/apache/pdfbox/pdmodel/font/PDType1CFont.java

Modified: pdfbox/trunk/fontbox/src/main/java/org/apache/fontbox/cff/CFFParser.java
URL: http://svn.apache.org/viewvc/pdfbox/trunk/fontbox/src/main/java/org/apache/fontbox/cff/CFFParser.java?rev=1900888&r1=1900887&r2=1900888&view=diff
==============================================================================
--- pdfbox/trunk/fontbox/src/main/java/org/apache/fontbox/cff/CFFParser.java (original)
+++ pdfbox/trunk/fontbox/src/main/java/org/apache/fontbox/cff/CFFParser.java Sat May 14 16:21:06 2022
@@ -28,6 +28,7 @@ import java.util.Map;
 
 import org.apache.commons.logging.Log;
 import org.apache.commons.logging.LogFactory;
+import org.apache.pdfbox.io.RandomAccessRead;
 
 
 /**
@@ -72,8 +73,9 @@ public class CFFParser
      */
     public List<CFFFont> parse(byte[] bytes, ByteSource source) throws IOException
     {
+        // TODO do we need to store the source data of the font? It isn't used at all
         this.source = source;
-        return parse(bytes);
+        return parse(new DataInputByteArray(bytes));
     }
     
     /**
@@ -83,16 +85,32 @@ public class CFFParser
      * @return the parsed CFF fonts
      * @throws IOException If there is an error reading from the stream
      */
-    public List<CFFFont> parse(byte[] bytes) throws IOException
+    public List<CFFFont> parse(RandomAccessRead randomAccessRead) throws IOException
     {
-        CFFDataInput input = new CFFDataInput(bytes);
+        // TODO do we need to store the source data of the font? It isn't used at all
+        byte[] bytes = new byte[(int) randomAccessRead.length()];
+        randomAccessRead.seek(0);
+        randomAccessRead.read(bytes);
+        randomAccessRead.seek(0);
+        this.source = new CFFBytesource(bytes);
+        return parse(new DataInputRandomAccessRead(randomAccessRead));
+    }
 
+    /**
+     * Parse CFF font using a byte array as input.
+     * 
+     * @param bytes the given byte array
+     * @return the parsed CFF fonts
+     * @throws IOException If there is an error reading from the stream
+     */
+    private List<CFFFont> parse(DataInput input) throws IOException
+    {
         String firstTag = readTagName(input);
         // try to determine which kind of font we have
         switch (firstTag)
         {
             case TAG_OTTO:
-                input = createTaggedCFFDataInput(input, bytes);
+                input = createTaggedCFFDataInput(input);
                 break;
             case TAG_TTCF:
                 throw new IOException("True Type Collection fonts are not supported.");
@@ -130,7 +148,7 @@ public class CFFParser
         return fonts;
     }
 
-    private CFFDataInput createTaggedCFFDataInput(CFFDataInput input, byte[] bytes) throws IOException
+    private DataInput createTaggedCFFDataInput(DataInput input) throws IOException
     {
         // this is OpenType font containing CFF data
         // so find CFF tag
@@ -150,42 +168,54 @@ public class CFFParser
             long length = readLong(input);
             if ("CFF ".equals(tagName))
             {
-                byte[] bytes2 = Arrays.copyOfRange(bytes, (int) offset, (int) (offset + length));
-                return new CFFDataInput(bytes2);
+                input.setPosition((int)offset);
+                byte[] bytes2 = input.readBytes((int) length);
+                return new DataInputByteArray(bytes2);
             }
         }
         throw new IOException("CFF tag not found in this OpenType font.");
     }
 
-    private static String readTagName(CFFDataInput input) throws IOException
+    private static String readTagName(DataInput input) throws IOException
     {
         byte[] b = input.readBytes(4);
         return new String(b, StandardCharsets.ISO_8859_1);
     }
 
-    private static long readLong(CFFDataInput input) throws IOException
+    private static long readLong(DataInput input) throws IOException
+    {
+        return (input.readUnsignedShort() << 16) | input.readUnsignedShort();
+    }
+
+    private static int readOffSize(DataInput input) throws IOException
     {
-        return (input.readCard16() << 16) | input.readCard16();
+        int offSize = input.readUnsignedByte();
+        if (offSize < 1 || offSize > 4)
+        {
+            throw new IOException("Illegal (< 1 or > 4) offSize value " + offSize
+                    + " in CFF font at position " + (input.getPosition() - 1));
+        }
+        return offSize;
     }
 
-    private static Header readHeader(CFFDataInput input) throws IOException
+    private static Header readHeader(DataInput input) throws IOException
     {
-        int major = input.readCard8();
-        int minor = input.readCard8();
-        int hdrSize = input.readCard8();
-        int offSize = input.readOffSize();
+        int major = input.readUnsignedByte();
+        int minor = input.readUnsignedByte();
+        int hdrSize = input.readUnsignedByte();
+        int offSize = readOffSize(input);
         return new Header(major, minor, hdrSize, offSize);
     }
 
-    private static int[] readIndexDataOffsets(CFFDataInput input) throws IOException
+    private static int[] readIndexDataOffsets(DataInput input) throws IOException
     {
-        int count = input.readCard16();
+        int count = input.readUnsignedShort();
         if (count == 0)
         {
             return new int[0];
         }
-        int offSize = input.readOffSize();
-        int[] offsets = new int[count+1];
+        int offSize = readOffSize(input);
+        int[] offsets = new int[count + 1];
         for (int i = 0; i <= count; i++)
         {
             int offset = input.readOffset(offSize);
@@ -198,7 +228,7 @@ public class CFFParser
         return offsets;
     }
 
-    private static byte[][] readIndexData(CFFDataInput input) throws IOException
+    private static byte[][] readIndexData(DataInput input) throws IOException
     {
         int[] offsets = readIndexDataOffsets(input);
         if (offsets.length == 0)
@@ -215,7 +245,7 @@ public class CFFParser
         return indexDataValues;
     }
 
-    private static String[] readStringIndexData(CFFDataInput input) throws IOException
+    private static String[] readStringIndexData(DataInput input) throws IOException
     {
         int[] offsets = readIndexDataOffsets(input);
         if (offsets.length == 0)
@@ -238,7 +268,7 @@ public class CFFParser
         return indexDataValues;
     }
 
-    private static DictData readDictData(CFFDataInput input) throws IOException
+    private static DictData readDictData(DataInput input) throws IOException
     {
         DictData dict = new DictData();
         while (input.hasRemaining())
@@ -248,7 +278,7 @@ public class CFFParser
         return dict;
     }
 
-    private static DictData readDictData(CFFDataInput input, int offset, int dictSize)
+    private static DictData readDictData(DataInput input, int offset, int dictSize)
             throws IOException
     {
         DictData dict = new DictData();
@@ -264,7 +294,7 @@ public class CFFParser
         return dict;
     }
 
-    private static DictData.Entry readEntry(CFFDataInput input) throws IOException
+    private static DictData.Entry readEntry(DataInput input) throws IOException
     {
         DictData.Entry entry = new DictData.Entry();
         while (true)
@@ -296,7 +326,7 @@ public class CFFParser
         return entry;
     }
 
-    private static String readOperator(CFFDataInput input, int b0) throws IOException
+    private static String readOperator(DataInput input, int b0) throws IOException
     {
         if (b0 == 12)
         {
@@ -307,7 +337,7 @@ public class CFFParser
 
     }
 
-    private static Integer readIntegerNumber(CFFDataInput input, int b0) throws IOException
+    private static Integer readIntegerNumber(DataInput input, int b0) throws IOException
     {
         if (b0 == 28)
         {
@@ -337,7 +367,7 @@ public class CFFParser
         }
     }
 
-    private static Double readRealNumber(CFFDataInput input) throws IOException
+    private static Double readRealNumber(DataInput input) throws IOException
     {
         StringBuilder sb = new StringBuilder();
         boolean done = false;
@@ -424,10 +454,10 @@ public class CFFParser
         }
     }
 
-    private CFFFont parseFont(CFFDataInput input, String name, byte[] topDictIndex) throws IOException
+    private CFFFont parseFont(DataInput input, String name, byte[] topDictIndex) throws IOException
     {
         // top dict
-        CFFDataInput topDictInput = new CFFDataInput(topDictIndex);
+        DataInputByteArray topDictInput = new DataInputByteArray(topDictIndex);
         DictData topDict = readDictData(topDictInput);
 
         // we don't support synthetic fonts
@@ -628,7 +658,8 @@ public class CFFParser
     /**
      * Parse dictionaries specific to a CIDFont.
      */
-    private void parseCIDFontDicts(CFFDataInput input, DictData topDict, CFFCIDFont font, int nrOfcharStrings)
+    private void parseCIDFontDicts(DataInput input, DictData topDict, CFFCIDFont font,
+            int nrOfcharStrings)
             throws IOException
     {
         // In a CIDKeyed Font, the Private dictionary isn't in the Top Dict but in the Font dict
@@ -653,7 +684,7 @@ public class CFFParser
 
         for (byte[] bytes : fdIndex)
         {
-            CFFDataInput fontDictInput = new CFFDataInput(bytes);
+            DataInputByteArray fontDictInput = new DataInputByteArray(bytes);
             DictData fontDict = readDictData(fontDictInput);
 
             // read private dict
@@ -734,7 +765,8 @@ public class CFFParser
     /**
      * Parse dictionaries specific to a Type 1-equivalent font.
      */
-    private void parseType1Dicts(CFFDataInput input, DictData topDict, CFFType1Font font, CFFCharset charset)
+    private void parseType1Dicts(DataInput input, DictData topDict, CFFType1Font font,
+            CFFCharset charset)
             throws IOException
     {
         // encoding
@@ -804,9 +836,9 @@ public class CFFParser
         return entry != null && entry.hasOperands() ? readString(entry.getNumber(0).intValue()) : null;
     }
 
-    private CFFEncoding readEncoding(CFFDataInput dataInput, CFFCharset charset) throws IOException
+    private CFFEncoding readEncoding(DataInput dataInput, CFFCharset charset) throws IOException
     {
-        int format = dataInput.readCard8();
+        int format = dataInput.readUnsignedByte();
         int baseFormat = format & 0x7f;
 
         switch (baseFormat)
@@ -820,15 +852,15 @@ public class CFFParser
         }
     }
 
-    private Format0Encoding readFormat0Encoding(CFFDataInput dataInput, CFFCharset charset,
+    private Format0Encoding readFormat0Encoding(DataInput dataInput, CFFCharset charset,
             int format)
             throws IOException
     {
-        Format0Encoding encoding = new Format0Encoding(dataInput.readCard8());
+        Format0Encoding encoding = new Format0Encoding(dataInput.readUnsignedByte());
         encoding.add(0, 0, ".notdef");
         for (int gid = 1; gid <= encoding.nCodes; gid++)
         {
-            int code = dataInput.readCard8();
+            int code = dataInput.readUnsignedByte();
             int sid = charset.getSIDForGID(gid);
             encoding.add(code, sid, readString(sid));
         }
@@ -839,16 +871,16 @@ public class CFFParser
         return encoding;
     }
 
-    private Format1Encoding readFormat1Encoding(CFFDataInput dataInput, CFFCharset charset,
+    private Format1Encoding readFormat1Encoding(DataInput dataInput, CFFCharset charset,
             int format) throws IOException
     {
-        Format1Encoding encoding = new Format1Encoding(dataInput.readCard8());
+        Format1Encoding encoding = new Format1Encoding(dataInput.readUnsignedByte());
         encoding.add(0, 0, ".notdef");
         int gid = 1;
         for (int i = 0; i < encoding.nRanges; i++)
         {
-            int rangeFirst = dataInput.readCard8(); // First code in range
-            int rangeLeft = dataInput.readCard8(); // Codes left in range (excluding first)
+            int rangeFirst = dataInput.readUnsignedByte(); // First code in range
+            int rangeLeft = dataInput.readUnsignedByte(); // Codes left in range (excluding first)
             for (int j = 0; j <= rangeLeft; j++)
             {
                 int sid = charset.getSIDForGID(gid);
@@ -863,15 +895,15 @@ public class CFFParser
         return encoding;
     }
 
-    private void readSupplement(CFFDataInput dataInput, CFFBuiltInEncoding encoding)
+    private void readSupplement(DataInput dataInput, CFFBuiltInEncoding encoding)
             throws IOException
     {
-        int nSups = dataInput.readCard8();
+        int nSups = dataInput.readUnsignedByte();
         encoding.supplement = new CFFBuiltInEncoding.Supplement[nSups];
         for (int i = 0; i < nSups; i++)
         {
-            int code = dataInput.readCard8();
-            int sid = dataInput.readSID();
+            int code = dataInput.readUnsignedByte();
+            int sid = dataInput.readUnsignedShort();
             encoding.supplement[i] = new CFFBuiltInEncoding.Supplement(code, sid, readString(sid));
             encoding.add(encoding.supplement[i]);
         }
@@ -884,9 +916,9 @@ public class CFFParser
      * @return the FDSelect data
      * @throws IOException
      */
-    private static FDSelect readFDSelect(CFFDataInput dataInput, int nGlyphs) throws IOException
+    private static FDSelect readFDSelect(DataInput dataInput, int nGlyphs) throws IOException
     {
-        int format = dataInput.readCard8();
+        int format = dataInput.readUnsignedByte();
         switch (format)
         {
             case 0:
@@ -905,13 +937,13 @@ public class CFFParser
      * @return the Format 0 of the FDSelect data
      * @throws IOException
      */
-    private static Format0FDSelect readFormat0FDSelect(CFFDataInput dataInput, int nGlyphs)
+    private static Format0FDSelect readFormat0FDSelect(DataInput dataInput, int nGlyphs)
             throws IOException
     {
         int[] fds = new int[nGlyphs];
         for (int i = 0; i < nGlyphs; i++)
         {
-            fds[i] = dataInput.readCard8();
+            fds[i] = dataInput.readUnsignedByte();
         }
         return new Format0FDSelect(fds);
     }
@@ -923,17 +955,17 @@ public class CFFParser
      * @return the Format 3 of the FDSelect data
      * @throws IOException
      */
-    private static Format3FDSelect readFormat3FDSelect(CFFDataInput dataInput)
+    private static Format3FDSelect readFormat3FDSelect(DataInput dataInput)
             throws IOException
     {
-        int nbRanges = dataInput.readCard16();
+        int nbRanges = dataInput.readUnsignedShort();
 
         Range3[] range3 = new Range3[nbRanges];
         for (int i = 0; i < nbRanges; i++)
         {
-            range3[i] = new Range3(dataInput.readCard16(), dataInput.readCard8());
+            range3[i] = new Range3(dataInput.readUnsignedShort(), dataInput.readUnsignedByte());
         }
-        return new Format3FDSelect(range3, dataInput.readCard16());
+        return new Format3FDSelect(range3, dataInput.readUnsignedShort());
     }
 
     /**
@@ -1037,10 +1069,10 @@ public class CFFParser
         }
     }
 
-    private CFFCharset readCharset(CFFDataInput dataInput, int nGlyphs, boolean isCIDFont)
+    private CFFCharset readCharset(DataInput dataInput, int nGlyphs, boolean isCIDFont)
             throws IOException
     {
-        int format = dataInput.readCard8();
+        int format = dataInput.readUnsignedByte();
         switch (format)
         {
             case 0:
@@ -1055,7 +1087,7 @@ public class CFFParser
         }
     }
 
-    private Format0Charset readFormat0Charset(CFFDataInput dataInput, int nGlyphs,
+    private Format0Charset readFormat0Charset(DataInput dataInput, int nGlyphs,
                                               boolean isCIDFont) throws IOException
     {
         Format0Charset charset = new Format0Charset(isCIDFont);
@@ -1064,7 +1096,7 @@ public class CFFParser
             charset.addCID(0, 0);
             for (int gid = 1; gid < nGlyphs; gid++)
             {
-                charset.addCID(gid, dataInput.readSID());
+                charset.addCID(gid, dataInput.readUnsignedShort());
             }
         }
         else
@@ -1072,14 +1104,14 @@ public class CFFParser
             charset.addSID(0, 0, ".notdef");
             for (int gid = 1; gid < nGlyphs; gid++)
             {
-                int sid = dataInput.readSID();
+                int sid = dataInput.readUnsignedShort();
                 charset.addSID(gid, sid, readString(sid));
             }
         }
         return charset;
     }
 
-    private Format1Charset readFormat1Charset(CFFDataInput dataInput, int nGlyphs,
+    private Format1Charset readFormat1Charset(DataInput dataInput, int nGlyphs,
                                               boolean isCIDFont) throws IOException
     {
         Format1Charset charset = new Format1Charset(isCIDFont);
@@ -1089,8 +1121,8 @@ public class CFFParser
             int gid = 1;
             while (gid < nGlyphs)
             {
-                int rangeFirst = dataInput.readSID();
-                int rangeLeft = dataInput.readCard8();
+                int rangeFirst = dataInput.readUnsignedShort();
+                int rangeLeft = dataInput.readUnsignedByte();
                 charset.addRangeMapping(new RangeMapping(gid, rangeFirst, rangeLeft));
                 gid += rangeLeft + 1;
             }
@@ -1101,8 +1133,8 @@ public class CFFParser
             int gid = 1;
             while (gid < nGlyphs)
             {
-                int rangeFirst = dataInput.readSID();
-                int rangeLeft = dataInput.readCard8() + 1;
+                int rangeFirst = dataInput.readUnsignedShort();
+                int rangeLeft = dataInput.readUnsignedByte() + 1;
                 for (int j = 0; j < rangeLeft; j++)
                 {
                     int sid = rangeFirst + j;
@@ -1114,7 +1146,7 @@ public class CFFParser
         return charset;
     }
 
-    private Format2Charset readFormat2Charset(CFFDataInput dataInput, int nGlyphs,
+    private Format2Charset readFormat2Charset(DataInput dataInput, int nGlyphs,
             boolean isCIDFont) throws IOException
     {
         Format2Charset charset = new Format2Charset(isCIDFont);
@@ -1124,8 +1156,8 @@ public class CFFParser
             int gid = 1;
             while (gid < nGlyphs)
             {
-                int first = dataInput.readSID();
-                int nLeft = dataInput.readCard16();
+                int first = dataInput.readUnsignedShort();
+                int nLeft = dataInput.readUnsignedShort();
                 charset.addRangeMapping(new RangeMapping(gid, first, nLeft));
                 gid += nLeft + 1;
             }
@@ -1136,8 +1168,8 @@ public class CFFParser
             int gid = 1;
             while (gid < nGlyphs)
             {
-                int first = dataInput.readSID();
-                int nLeft = dataInput.readCard16() + 1;
+                int first = dataInput.readUnsignedShort();
+                int nLeft = dataInput.readUnsignedShort() + 1;
                 for (int j = 0; j < nLeft; j++)
                 {
                     int sid = first + j;
@@ -1580,6 +1612,25 @@ public class CFFParser
         }
     }
 
+    /**
+     * Allows bytes to be re-read later by CFFParser.
+     */
+    private static class CFFBytesource implements CFFParser.ByteSource
+    {
+        private final byte[] bytes;
+
+        CFFBytesource(byte[] bytes)
+        {
+            this.bytes = bytes;
+        }
+
+        @Override
+        public byte[] getBytes() throws IOException
+        {
+            return bytes;
+        }
+    }
+
     @Override
     public String toString()
     {

Modified: pdfbox/trunk/fontbox/src/main/java/org/apache/fontbox/cff/DataInput.java
URL: http://svn.apache.org/viewvc/pdfbox/trunk/fontbox/src/main/java/org/apache/fontbox/cff/DataInput.java?rev=1900888&r1=1900887&r2=1900888&view=diff
==============================================================================
--- pdfbox/trunk/fontbox/src/main/java/org/apache/fontbox/cff/DataInput.java (original)
+++ pdfbox/trunk/fontbox/src/main/java/org/apache/fontbox/cff/DataInput.java Sat May 14 16:21:06 2022
@@ -19,42 +19,24 @@ package org.apache.fontbox.cff;
 import java.io.IOException;
 
 /**
- * This class contains some functionality to read a byte buffer.
+ * This interface defines some functionality to read a CFF font.
  * 
  * @author Villu Ruusmann
  */
-public class DataInput
+public interface DataInput
 {
 
-    private final byte[] inputBuffer;
-    private int bufferPosition = 0;
-
-    /**
-     * Constructor.
-     * @param buffer the buffer to be read
-     */
-    public DataInput(byte[] buffer)
-    {
-        inputBuffer = buffer;
-    }
-
     /**
      * Determines if there are any bytes left to read or not. 
      * @return true if there are any bytes left to read
      */
-    public boolean hasRemaining()
-    {
-        return bufferPosition < inputBuffer.length;
-    }
+    public boolean hasRemaining() throws IOException;
 
     /**
      * Returns the current position.
      * @return current position
      */
-    public int getPosition()
-    {
-        return bufferPosition;
-    }
+    public int getPosition() throws IOException;
 
     /**
      * Sets the current position to the given value.
@@ -62,47 +44,21 @@ public class DataInput
      * @param position the given position
      * @throws IOException if the new position ist out of range
      */
-    public void setPosition(int position) throws IOException
-    {
-        if (position < 0)
-        {
-            throw new IOException("position is negative");
-        }
-        if (position >= inputBuffer.length)
-        {
-            throw new IOException(
-                    "New position is out of range " + position + " >= " + inputBuffer.length);
-        }
-        bufferPosition = position;
-    }
+    public void setPosition(int position) throws IOException;
 
     /**
      * Read one single byte from the buffer.
      * @return the byte
      * @throws IOException if an error occurs during reading
      */
-    public byte readByte() throws IOException
-    {
-        if (!hasRemaining())
-        {
-            throw new IOException("End off buffer reached");
-        }
-        return inputBuffer[bufferPosition++];
-    }
+    public byte readByte() throws IOException;
 
     /**
      * Read one single unsigned byte from the buffer.
      * @return the unsigned byte as int
      * @throws IOException if an error occurs during reading
      */
-    public int readUnsignedByte() throws IOException
-    {
-        if (!hasRemaining())
-        {
-            throw new IOException("End off buffer reached");
-        }
-        return inputBuffer[bufferPosition++] & 0xff;
-    }
+    public int readUnsignedByte() throws IOException;
 
     /**
      * Peeks one single unsigned byte from the buffer.
@@ -111,26 +67,14 @@ public class DataInput
      * @return the unsigned byte as int
      * @throws IOException if an error occurs during reading
      */
-    public int peekUnsignedByte(int offset) throws IOException
-    {
-        if (offset < 0)
-        {
-            throw new IOException("offset is negative");
-        }
-        if (bufferPosition + offset >= inputBuffer.length)
-        {
-            throw new IOException("Offset position is out of range " + (bufferPosition + offset)
-                    + " >= " + inputBuffer.length);
-        }
-        return inputBuffer[bufferPosition + offset] & 0xff;
-    }
+    public int peekUnsignedByte(int offset) throws IOException;
 
     /**
      * Read one single short value from the buffer.
      * @return the short value
      * @throws IOException if an error occurs during reading
      */
-    public short readShort() throws IOException
+    default short readShort() throws IOException
     {
         return (short) readUnsignedShort();
     }
@@ -140,7 +84,7 @@ public class DataInput
      * @return the unsigned short value as int
      * @throws IOException if an error occurs during reading
      */
-    public int readUnsignedShort() throws IOException
+    default int readUnsignedShort() throws IOException
     {
         int b1 = readUnsignedByte();
         int b2 = readUnsignedByte();
@@ -152,7 +96,7 @@ public class DataInput
      * @return the int value
      * @throws IOException if an error occurs during reading
      */
-    public int readInt() throws IOException
+    default int readInt() throws IOException
     {
         int b1 = readUnsignedByte();
         int b2 = readUnsignedByte();
@@ -167,24 +111,23 @@ public class DataInput
      * @return an array with containing the bytes from the buffer 
      * @throws IOException if an error occurs during reading
      */
-    public byte[] readBytes(int length) throws IOException
+    public byte[] readBytes(int length) throws IOException;
+
+    public int length() throws IOException;
+
+    /**
+     * Read the offset from the buffer.
+     * @param offSize the given offsize
+     * @return the offset
+     * @throws IOException if an error occurs during reading
+     */
+    default int readOffset(int offSize) throws IOException
     {
-        if (length < 0)
+        int value = 0;
+        for (int i = 0; i < offSize; i++)
         {
-            throw new IOException("length is negative"); 
+            value = value << 8 | readUnsignedByte();
         }
-        if (inputBuffer.length - bufferPosition < length)
-        {
-            throw new IOException("Premature end of buffer reached");
-        }
-        byte[] bytes = new byte[length];
-        System.arraycopy(inputBuffer, bufferPosition, bytes, 0, length);
-        bufferPosition += length;
-        return bytes;
-    }
-
-    public int length()
-    {
-        return inputBuffer.length;
+        return value;
     }
 }
\ No newline at end of file

Added: pdfbox/trunk/fontbox/src/main/java/org/apache/fontbox/cff/DataInputByteArray.java
URL: http://svn.apache.org/viewvc/pdfbox/trunk/fontbox/src/main/java/org/apache/fontbox/cff/DataInputByteArray.java?rev=1900888&view=auto
==============================================================================
--- pdfbox/trunk/fontbox/src/main/java/org/apache/fontbox/cff/DataInputByteArray.java (added)
+++ pdfbox/trunk/fontbox/src/main/java/org/apache/fontbox/cff/DataInputByteArray.java Sat May 14 16:21:06 2022
@@ -0,0 +1,162 @@
+/*
+ * 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.fontbox.cff;
+
+import java.io.IOException;
+
+/**
+ * This class implements the DataInput interface using a byte buffer as source.
+ * 
+ * @author Villu Ruusmann
+ */
+public class DataInputByteArray implements DataInput
+{
+
+    private final byte[] inputBuffer;
+    private int bufferPosition = 0;
+
+    /**
+     * Constructor.
+     * @param buffer the buffer to be read
+     */
+    public DataInputByteArray(byte[] buffer)
+    {
+        inputBuffer = buffer;
+    }
+
+    /**
+     * Determines if there are any bytes left to read or not. 
+     * @return true if there are any bytes left to read
+     */
+    @Override
+    public boolean hasRemaining() throws IOException
+    {
+        return bufferPosition < inputBuffer.length;
+    }
+
+    /**
+     * Returns the current position.
+     * @return current position
+     */
+    @Override
+    public int getPosition()
+    {
+        return bufferPosition;
+    }
+
+    /**
+     * Sets the current position to the given value.
+     * 
+     * @param position the given position
+     * @throws IOException if the new position ist out of range
+     */
+    @Override
+    public void setPosition(int position) throws IOException
+    {
+        if (position < 0)
+        {
+            throw new IOException("position is negative");
+        }
+        if (position >= inputBuffer.length)
+        {
+            throw new IOException(
+                    "New position is out of range " + position + " >= " + inputBuffer.length);
+        }
+        bufferPosition = position;
+    }
+
+    /**
+     * Read one single byte from the buffer.
+     * @return the byte
+     * @throws IOException if an error occurs during reading
+     */
+    @Override
+    public byte readByte() throws IOException
+    {
+        if (!hasRemaining())
+        {
+            throw new IOException("End off buffer reached");
+        }
+        return inputBuffer[bufferPosition++];
+    }
+
+    /**
+     * Read one single unsigned byte from the buffer.
+     * @return the unsigned byte as int
+     * @throws IOException if an error occurs during reading
+     */
+    @Override
+    public int readUnsignedByte() throws IOException
+    {
+        if (!hasRemaining())
+        {
+            throw new IOException("End off buffer reached");
+        }
+        return inputBuffer[bufferPosition++] & 0xff;
+    }
+
+    /**
+     * Peeks one single unsigned byte from the buffer.
+     * 
+     * @param offset offset to the byte to be peeked
+     * @return the unsigned byte as int
+     * @throws IOException if an error occurs during reading
+     */
+    @Override
+    public int peekUnsignedByte(int offset) throws IOException
+    {
+        if (offset < 0)
+        {
+            throw new IOException("offset is negative");
+        }
+        if (bufferPosition + offset >= inputBuffer.length)
+        {
+            throw new IOException("Offset position is out of range " + (bufferPosition + offset)
+                    + " >= " + inputBuffer.length);
+        }
+        return inputBuffer[bufferPosition + offset] & 0xff;
+    }
+
+    /**
+     * Read a number of single byte values from the buffer.
+     * @param length the number of bytes to be read
+     * @return an array with containing the bytes from the buffer 
+     * @throws IOException if an error occurs during reading
+     */
+    @Override
+    public byte[] readBytes(int length) throws IOException
+    {
+        if (length < 0)
+        {
+            throw new IOException("length is negative"); 
+        }
+        if (inputBuffer.length - bufferPosition < length)
+        {
+            throw new IOException("Premature end of buffer reached");
+        }
+        byte[] bytes = new byte[length];
+        System.arraycopy(inputBuffer, bufferPosition, bytes, 0, length);
+        bufferPosition += length;
+        return bytes;
+    }
+
+    @Override
+    public int length() throws IOException
+    {
+        return inputBuffer.length;
+    }
+}
\ No newline at end of file

Propchange: pdfbox/trunk/fontbox/src/main/java/org/apache/fontbox/cff/DataInputByteArray.java
------------------------------------------------------------------------------
    svn:eol-style = native

Added: pdfbox/trunk/fontbox/src/main/java/org/apache/fontbox/cff/DataInputRandomAccessRead.java
URL: http://svn.apache.org/viewvc/pdfbox/trunk/fontbox/src/main/java/org/apache/fontbox/cff/DataInputRandomAccessRead.java?rev=1900888&view=auto
==============================================================================
--- pdfbox/trunk/fontbox/src/main/java/org/apache/fontbox/cff/DataInputRandomAccessRead.java (added)
+++ pdfbox/trunk/fontbox/src/main/java/org/apache/fontbox/cff/DataInputRandomAccessRead.java Sat May 14 16:21:06 2022
@@ -0,0 +1,170 @@
+/*
+ * 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.fontbox.cff;
+
+import java.io.IOException;
+import org.apache.pdfbox.io.RandomAccessRead;
+
+/**
+ * This class implements the DataInput interface using a RandomAccessRead as source.
+ */
+public class DataInputRandomAccessRead implements DataInput
+{
+
+    private final RandomAccessRead randomAccessRead;
+
+    /**
+     * Constructor.
+     * 
+     * @param randomAccessRead the source to be read from
+     */
+    public DataInputRandomAccessRead(RandomAccessRead randomAccessRead)
+    {
+        this.randomAccessRead = randomAccessRead;
+    }
+
+    /**
+     * Determines if there are any bytes left to read or not. 
+     * @return true if there are any bytes left to read
+     */
+    @Override
+    public boolean hasRemaining() throws IOException
+    {
+        return randomAccessRead.available() > 0;
+    }
+
+    /**
+     * Returns the current position.
+     * @return current position
+     */
+    @Override
+    public int getPosition() throws IOException
+    {
+        return (int) randomAccessRead.getPosition();
+    }
+
+    /**
+     * Sets the current position to the given value.
+     * 
+     * @param position the given position
+     * @throws IOException if the new position ist out of range
+     */
+    @Override
+    public void setPosition(int position) throws IOException
+    {
+        if (position < 0)
+        {
+            throw new IOException("position is negative");
+        }
+        if (position >= randomAccessRead.length())
+        {
+            throw new IOException("New position is out of range " + position + " >= "
+                    + randomAccessRead.length());
+        }
+        randomAccessRead.seek(position);
+    }
+
+    /**
+     * Read one single byte from the buffer.
+     * @return the byte
+     * @throws IOException if an error occurs during reading
+     */
+    @Override
+    public byte readByte() throws IOException
+    {
+        if (!hasRemaining())
+        {
+            throw new IOException("End off buffer reached");
+        }
+        return (byte) randomAccessRead.read();
+    }
+
+    /**
+     * Read one single unsigned byte from the buffer.
+     * @return the unsigned byte as int
+     * @throws IOException if an error occurs during reading
+     */
+    @Override
+    public int readUnsignedByte() throws IOException
+    {
+        if (!hasRemaining())
+        {
+            throw new IOException("End off buffer reached");
+        }
+        return randomAccessRead.read();
+    }
+
+    /**
+     * Peeks one single unsigned byte from the buffer.
+     * 
+     * @param offset offset to the byte to be peeked
+     * @return the unsigned byte as int
+     * @throws IOException if an error occurs during reading
+     */
+    @Override
+    public int peekUnsignedByte(int offset) throws IOException
+    {
+        if (offset < 0)
+        {
+            throw new IOException("offset is negative");
+        }
+        if (offset == 0)
+        {
+            return randomAccessRead.peek();
+        }
+        long currentPosition = randomAccessRead.getPosition();
+        if (currentPosition + offset >= randomAccessRead.length())
+        {
+            throw new IOException("Offset position is out of range " + (currentPosition + offset)
+                    + " >= " + randomAccessRead.length());
+        }
+        randomAccessRead.seek(currentPosition + offset);
+        int peekValue = randomAccessRead.read();
+        randomAccessRead.seek(currentPosition);
+        return peekValue;
+    }
+
+    /**
+     * Read a number of single byte values from the buffer.
+     * @param length the number of bytes to be read
+     * @return an array with containing the bytes from the buffer 
+     * @throws IOException if an error occurs during reading
+     */
+    @Override
+    public byte[] readBytes(int length) throws IOException
+    {
+        if (length < 0)
+        {
+            throw new IOException("length is negative");
+        }
+        if (randomAccessRead.length() - randomAccessRead.getPosition() < length)
+        {
+            throw new IOException("Premature end of buffer reached");
+        }
+        byte[] bytes = new byte[length];
+        for (int i = 0; i < length; i++)
+            bytes[i] = readByte();
+        return bytes;
+    }
+
+    @Override
+    public int length() throws IOException
+    {
+        return (int) randomAccessRead.length();
+    }
+
+}
\ No newline at end of file

Propchange: pdfbox/trunk/fontbox/src/main/java/org/apache/fontbox/cff/DataInputRandomAccessRead.java
------------------------------------------------------------------------------
    svn:eol-style = native

Modified: pdfbox/trunk/fontbox/src/main/java/org/apache/fontbox/cff/Type1CharStringParser.java
URL: http://svn.apache.org/viewvc/pdfbox/trunk/fontbox/src/main/java/org/apache/fontbox/cff/Type1CharStringParser.java?rev=1900888&r1=1900887&r2=1900888&view=diff
==============================================================================
--- pdfbox/trunk/fontbox/src/main/java/org/apache/fontbox/cff/Type1CharStringParser.java (original)
+++ pdfbox/trunk/fontbox/src/main/java/org/apache/fontbox/cff/Type1CharStringParser.java Sat May 14 16:21:06 2022
@@ -76,7 +76,7 @@ public class Type1CharStringParser
     private List<Object> parse(byte[] bytes, List<byte[]> subrs, List<Object> sequence)
             throws IOException
     {
-        DataInput input = new DataInput(bytes);
+        DataInput input = new DataInputByteArray(bytes);
         while (input.hasRemaining())
         {
             int b0 = input.readUnsignedByte();

Modified: pdfbox/trunk/fontbox/src/main/java/org/apache/fontbox/cff/Type2CharStringParser.java
URL: http://svn.apache.org/viewvc/pdfbox/trunk/fontbox/src/main/java/org/apache/fontbox/cff/Type2CharStringParser.java?rev=1900888&r1=1900887&r2=1900888&view=diff
==============================================================================
--- pdfbox/trunk/fontbox/src/main/java/org/apache/fontbox/cff/Type2CharStringParser.java (original)
+++ pdfbox/trunk/fontbox/src/main/java/org/apache/fontbox/cff/Type2CharStringParser.java Sat May 14 16:21:06 2022
@@ -74,7 +74,7 @@ public class Type2CharStringParser
     private List<Object> parseSequence(byte[] bytes, byte[][] globalSubrIndex,
             byte[][] localSubrIndex) throws IOException
     {
-        DataInput input = new DataInput(bytes);
+        DataInput input = new DataInputByteArray(bytes);
         boolean localSubroutineIndexProvided = localSubrIndex != null && localSubrIndex.length > 0;
         boolean globalSubroutineIndexProvided = globalSubrIndex != null && globalSubrIndex.length > 0;
 

Modified: pdfbox/trunk/fontbox/src/test/java/org/apache/fontbox/cff/CFFParserTest.java
URL: http://svn.apache.org/viewvc/pdfbox/trunk/fontbox/src/test/java/org/apache/fontbox/cff/CFFParserTest.java?rev=1900888&r1=1900887&r2=1900888&view=diff
==============================================================================
--- pdfbox/trunk/fontbox/src/test/java/org/apache/fontbox/cff/CFFParserTest.java (original)
+++ pdfbox/trunk/fontbox/src/test/java/org/apache/fontbox/cff/CFFParserTest.java Sat May 14 16:21:06 2022
@@ -20,14 +20,12 @@ import static org.junit.jupiter.api.Asse
 import static org.junit.jupiter.api.Assertions.assertNotNull;
 import static org.junit.jupiter.api.Assertions.assertTrue;
 
-import java.io.ByteArrayOutputStream;
 import java.io.IOException;
-import java.nio.file.Files;
-import java.nio.file.Paths;
 import java.util.Arrays;
 import java.util.List;
 
 import org.apache.fontbox.util.BoundingBox;
+import org.apache.pdfbox.io.RandomAccessReadBufferedFile;
 import org.junit.jupiter.api.BeforeAll;
 import org.junit.jupiter.api.Test;
 
@@ -205,10 +203,9 @@ class CFFParserTest
 
     private static List<CFFFont> readFont(String filename) throws IOException
     {
-        ByteArrayOutputStream content = new ByteArrayOutputStream();
-        Files.copy(Paths.get(filename), content);
+        RandomAccessReadBufferedFile randomAccessRead = new RandomAccessReadBufferedFile(filename);
         CFFParser parser = new CFFParser();
-        return parser.parse(content.toByteArray());
+        return parser.parse(randomAccessRead);
     }
 
     private void assertNumberList(String message, int[] expected, List<Number> found)

Added: pdfbox/trunk/fontbox/src/test/java/org/apache/fontbox/cff/DataInputRandomAccessTest.java
URL: http://svn.apache.org/viewvc/pdfbox/trunk/fontbox/src/test/java/org/apache/fontbox/cff/DataInputRandomAccessTest.java?rev=1900888&view=auto
==============================================================================
--- pdfbox/trunk/fontbox/src/test/java/org/apache/fontbox/cff/DataInputRandomAccessTest.java (added)
+++ pdfbox/trunk/fontbox/src/test/java/org/apache/fontbox/cff/DataInputRandomAccessTest.java Sat May 14 16:21:06 2022
@@ -0,0 +1,137 @@
+/*
+ * Copyright 2017 The Apache Software Foundation.
+ *
+ * Licensed 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.fontbox.cff;
+
+import static org.junit.jupiter.api.Assertions.assertArrayEquals;
+import static org.junit.jupiter.api.Assertions.assertEquals;
+import static org.junit.jupiter.api.Assertions.assertThrows;
+import static org.junit.jupiter.api.Assertions.assertTrue;
+
+import java.io.IOException;
+
+import org.apache.pdfbox.io.RandomAccessReadBuffer;
+import org.junit.jupiter.api.Test;
+
+class DataInputRandomAccessTest
+{
+    @Test
+    void testReadBytes() throws IOException
+    {
+        byte[] data = new byte[] { 0, -1, 2, -3, 4, -5, 6, -7, 8, -9 };
+        DataInput dataInput = new DataInputRandomAccessRead(new RandomAccessReadBuffer(data));
+        assertThrows(IOException.class, () -> dataInput.readBytes(20));
+        assertArrayEquals(new byte[] { 0 }, dataInput.readBytes(1));
+        assertArrayEquals(new byte[] { -1, 2, -3 }, dataInput.readBytes(3));
+        dataInput.setPosition(6);
+        assertArrayEquals(new byte[] { 6, -7, 8 }, dataInput.readBytes(3));
+        assertThrows(IOException.class, () -> dataInput.readBytes(-1));
+        assertThrows(IOException.class, () -> dataInput.readBytes(5));
+    }
+
+    @Test
+    void testReadByte() throws IOException
+    {
+        byte[] data = new byte[] { 0, -1, 2, -3, 4, -5, 6, -7, 8, -9 };
+        DataInput dataInput = new DataInputRandomAccessRead(new RandomAccessReadBuffer(data));
+        assertEquals(0, dataInput.readByte());
+        assertEquals(-1, dataInput.readByte());
+        dataInput.setPosition(6);
+        assertEquals(6, dataInput.readByte());
+        assertEquals(-7, dataInput.readByte());
+        dataInput.setPosition(dataInput.length() - 1);
+        assertEquals(-9, dataInput.readByte());
+        assertThrows(IOException.class, () -> dataInput.readByte());
+    }
+
+    @Test
+    void testReadUnsignedByte() throws IOException
+    {
+        byte[] data = new byte[] { 0, -1, 2, -3, 4, -5, 6, -7, 8, -9 };
+        DataInput dataInput = new DataInputRandomAccessRead(new RandomAccessReadBuffer(data));
+        assertEquals(0, dataInput.readUnsignedByte());
+        assertEquals(255, dataInput.readUnsignedByte());
+        dataInput.setPosition(6);
+        assertEquals(6, dataInput.readUnsignedByte());
+        assertEquals(249, dataInput.readUnsignedByte());
+        dataInput.setPosition(dataInput.length() - 1);
+        assertEquals(247, dataInput.readUnsignedByte());
+        assertThrows(IOException.class, () -> dataInput.readUnsignedByte());
+    }
+
+    @Test
+    void testBasics() throws IOException
+    {
+        byte[] data = new byte[] { 0, -1, 2, -3, 4, -5, 6, -7, 8, -9 };
+        DataInput dataInput = new DataInputRandomAccessRead(new RandomAccessReadBuffer(data));
+        assertEquals(10, dataInput.length());
+        assertTrue(dataInput.hasRemaining());
+        assertThrows(IOException.class, () -> dataInput.setPosition(-1));
+        assertThrows(IOException.class, () -> dataInput.setPosition(dataInput.length()));
+    }
+
+    @Test
+    void testPeek() throws IOException
+    {
+        byte[] data = new byte[] { 0, -1, 2, -3, 4, -5, 6, -7, 8, -9 };
+        DataInput dataInput = new DataInputRandomAccessRead(new RandomAccessReadBuffer(data));
+        assertEquals(0, dataInput.peekUnsignedByte(0));
+        assertEquals(251, dataInput.peekUnsignedByte(5));
+        assertThrows(IOException.class, () -> dataInput.peekUnsignedByte(-1));
+        assertThrows(IOException.class, () -> dataInput.peekUnsignedByte(dataInput.length()));
+    }
+
+    @Test
+    void testReadShort() throws IOException
+    {
+        byte[] data = new byte[] { 0x00, 0x0F, (byte) 0xAA, 0, (byte) 0xFE, (byte) 0xFF };
+        DataInput dataInput = new DataInputRandomAccessRead(new RandomAccessReadBuffer(data));
+        assertEquals((short) 0x000F, dataInput.readShort());
+        assertEquals((short) 0xAA00, dataInput.readShort());
+        assertEquals((short) 0xFEFF, dataInput.readShort());
+        assertThrows(IOException.class, () -> dataInput.readShort());
+    }
+
+    @Test
+    void testReadUnsignedShort() throws IOException
+    {
+        byte[] data = new byte[] { 0x00, 0x0F, (byte) 0xAA, 0, (byte) 0xFE, (byte) 0xFF };
+        DataInput dataInput = new DataInputRandomAccessRead(new RandomAccessReadBuffer(data));
+        assertEquals(0x000F, dataInput.readUnsignedShort());
+        assertEquals(0xAA00, dataInput.readUnsignedShort());
+        assertEquals(0xFEFF, dataInput.readUnsignedShort());
+        assertThrows(IOException.class, () -> dataInput.readUnsignedShort());
+
+        byte[] data2 = new byte[] { 0x00 };
+        DataInput dataInput2 = new DataInputRandomAccessRead(new RandomAccessReadBuffer(data2));
+        assertThrows(IOException.class, () -> dataInput2.readUnsignedShort());
+    }
+
+    @Test
+    void testReadInt() throws IOException
+    {
+        byte[] data = new byte[] { 0x00, 0x0F, (byte) 0xAA, 0, (byte) 0xFE, (byte) 0xFF, 0x30,
+                0x50 };
+        DataInput dataInput = new DataInputRandomAccessRead(new RandomAccessReadBuffer(data));
+        assertEquals(0x000FAA00, dataInput.readInt());
+        assertEquals(0xFEFF3050, dataInput.readInt());
+        assertThrows(IOException.class, () -> dataInput.readInt());
+
+        byte[] data2 = new byte[] { 0x00, 0x0F, (byte) 0xAA };
+        DataInput dataInput2 = new DataInputRandomAccessRead(new RandomAccessReadBuffer(data2));
+        assertThrows(IOException.class, () -> dataInput2.readInt());
+
+    }
+}

Propchange: pdfbox/trunk/fontbox/src/test/java/org/apache/fontbox/cff/DataInputRandomAccessTest.java
------------------------------------------------------------------------------
    svn:eol-style = native

Modified: pdfbox/trunk/fontbox/src/test/java/org/apache/fontbox/cff/DataInputTest.java
URL: http://svn.apache.org/viewvc/pdfbox/trunk/fontbox/src/test/java/org/apache/fontbox/cff/DataInputTest.java?rev=1900888&r1=1900887&r2=1900888&view=diff
==============================================================================
--- pdfbox/trunk/fontbox/src/test/java/org/apache/fontbox/cff/DataInputTest.java (original)
+++ pdfbox/trunk/fontbox/src/test/java/org/apache/fontbox/cff/DataInputTest.java Sat May 14 16:21:06 2022
@@ -30,7 +30,7 @@ class DataInputTest
     void testReadBytes() throws IOException
     {
         byte[] data = new byte[] { 0, -1, 2, -3, 4, -5, 6, -7, 8, -9 };
-        DataInput dataInput = new DataInput(data);
+        DataInput dataInput = new DataInputByteArray(data);
         assertThrows(IOException.class, () -> dataInput.readBytes(20));
         assertArrayEquals(new byte[] { 0 }, dataInput.readBytes(1));
         assertArrayEquals(new byte[] { -1, 2, -3 }, dataInput.readBytes(3));
@@ -44,7 +44,7 @@ class DataInputTest
     void testReadByte() throws IOException
     {
         byte[] data = new byte[] { 0, -1, 2, -3, 4, -5, 6, -7, 8, -9 };
-        DataInput dataInput = new DataInput(data);
+        DataInput dataInput = new DataInputByteArray(data);
         assertEquals(0, dataInput.readByte());
         assertEquals(-1, dataInput.readByte());
         dataInput.setPosition(6);
@@ -59,7 +59,7 @@ class DataInputTest
     void testReadUnsignedByte() throws IOException
     {
         byte[] data = new byte[] { 0, -1, 2, -3, 4, -5, 6, -7, 8, -9 };
-        DataInput dataInput = new DataInput(data);
+        DataInput dataInput = new DataInputByteArray(data);
         assertEquals(0, dataInput.readUnsignedByte());
         assertEquals(255, dataInput.readUnsignedByte());
         dataInput.setPosition(6);
@@ -74,7 +74,7 @@ class DataInputTest
     void testBasics() throws IOException
     {
         byte[] data = new byte[] { 0, -1, 2, -3, 4, -5, 6, -7, 8, -9 };
-        DataInput dataInput = new DataInput(data);
+        DataInput dataInput = new DataInputByteArray(data);
         assertEquals(10, dataInput.length());
         assertTrue(dataInput.hasRemaining());
         assertThrows(IOException.class, () -> dataInput.setPosition(-1));
@@ -85,7 +85,7 @@ class DataInputTest
     void testPeek() throws IOException
     {
         byte[] data = new byte[] { 0, -1, 2, -3, 4, -5, 6, -7, 8, -9 };
-        DataInput dataInput = new DataInput(data);
+        DataInput dataInput = new DataInputByteArray(data);
         assertEquals(0, dataInput.peekUnsignedByte(0));
         assertEquals(251, dataInput.peekUnsignedByte(5));
         assertThrows(IOException.class, () -> dataInput.peekUnsignedByte(-1));
@@ -96,7 +96,7 @@ class DataInputTest
     void testReadShort() throws IOException
     {
         byte[] data = new byte[] { 0x00, 0x0F, (byte) 0xAA, 0, (byte) 0xFE, (byte) 0xFF };
-        DataInput dataInput = new DataInput(data);
+        DataInput dataInput = new DataInputByteArray(data);
         assertEquals((short) 0x000F, dataInput.readShort());
         assertEquals((short) 0xAA00, dataInput.readShort());
         assertEquals((short) 0xFEFF, dataInput.readShort());
@@ -107,14 +107,14 @@ class DataInputTest
     void testReadUnsignedShort() throws IOException
     {
         byte[] data = new byte[] { 0x00, 0x0F, (byte) 0xAA, 0, (byte) 0xFE, (byte) 0xFF };
-        DataInput dataInput = new DataInput(data);
+        DataInput dataInput = new DataInputByteArray(data);
         assertEquals(0x000F, dataInput.readUnsignedShort());
         assertEquals(0xAA00, dataInput.readUnsignedShort());
         assertEquals(0xFEFF, dataInput.readUnsignedShort());
         assertThrows(IOException.class, () -> dataInput.readUnsignedShort());
 
         byte[] data2 = new byte[] { 0x00 };
-        DataInput dataInput2 = new DataInput(data2);
+        DataInput dataInput2 = new DataInputByteArray(data2);
         assertThrows(IOException.class, () -> dataInput2.readUnsignedShort());
     }
 
@@ -123,13 +123,13 @@ class DataInputTest
     {
         byte[] data = new byte[] { 0x00, 0x0F, (byte) 0xAA, 0, (byte) 0xFE, (byte) 0xFF, 0x30,
                 0x50 };
-        DataInput dataInput = new DataInput(data);
+        DataInput dataInput = new DataInputByteArray(data);
         assertEquals(0x000FAA00, dataInput.readInt());
         assertEquals(0xFEFF3050, dataInput.readInt());
         assertThrows(IOException.class, () -> dataInput.readInt());
 
         byte[] data2 = new byte[] { 0x00, 0x0F, (byte) 0xAA };
-        DataInput dataInput2 = new DataInput(data2);
+        DataInput dataInput2 = new DataInputByteArray(data2);
         assertThrows(IOException.class, () -> dataInput2.readInt());
 
     }

Modified: pdfbox/trunk/pdfbox/src/main/java/org/apache/pdfbox/pdmodel/font/PDCIDFontType0.java
URL: http://svn.apache.org/viewvc/pdfbox/trunk/pdfbox/src/main/java/org/apache/pdfbox/pdmodel/font/PDCIDFontType0.java?rev=1900888&r1=1900887&r2=1900888&view=diff
==============================================================================
--- pdfbox/trunk/pdfbox/src/main/java/org/apache/pdfbox/pdmodel/font/PDCIDFontType0.java (original)
+++ pdfbox/trunk/pdfbox/src/main/java/org/apache/pdfbox/pdmodel/font/PDCIDFontType0.java Sat May 14 16:21:06 2022
@@ -33,6 +33,7 @@ import org.apache.fontbox.cff.CFFType1Fo
 import org.apache.fontbox.cff.Type2CharString;
 import org.apache.fontbox.util.BoundingBox;
 import org.apache.pdfbox.cos.COSDictionary;
+import org.apache.pdfbox.io.RandomAccessRead;
 import org.apache.pdfbox.pdmodel.common.PDRectangle;
 import org.apache.pdfbox.pdmodel.common.PDStream;
 import org.apache.pdfbox.util.Matrix;
@@ -73,30 +74,33 @@ public class PDCIDFontType0 extends PDCI
         super(fontDictionary, parent);
 
         PDFontDescriptor fd = getFontDescriptor();
-        byte[] bytes = null;
+        RandomAccessRead randomAccessRead = null;
         if (fd != null)
         {
             PDStream ff3Stream = fd.getFontFile3();
             if (ff3Stream != null)
             {
-                bytes = ff3Stream.toByteArray();
+                randomAccessRead = ff3Stream.getCOSObject().createView();
             }
         }
 
         boolean fontIsDamaged = false;
         CFFFont cffFont = null;
-        if (bytes != null && bytes.length > 0 && (bytes[0] & 0xff) == '%')
+        if (randomAccessRead != null && randomAccessRead.length() > 0
+                && randomAccessRead.peek() == '%')
         {
             // PDFBOX-2642 contains a corrupt PFB font instead of a CFF
             LOG.warn("Found PFB but expected embedded CFF font " + fd.getFontName());
             fontIsDamaged = true;
+            randomAccessRead.close();
         }
-        else if (bytes != null)
+        else if (randomAccessRead != null)
         {
             CFFParser cffParser = new CFFParser();
             try
             {
-                cffFont = cffParser.parse(bytes, new FF3ByteSource()).get(0);
+                cffFont = cffParser.parse(randomAccessRead).get(0);
+                randomAccessRead.close();
             }
             catch (IOException e)
             {
@@ -470,12 +474,4 @@ public class PDCIDFontType0 extends PDCI
         return 500;
     }
 
-    private class FF3ByteSource implements CFFParser.ByteSource
-    {
-        @Override
-        public byte[] getBytes() throws IOException
-        {
-            return getFontDescriptor().getFontFile3().toByteArray();
-        }
-    }
 }

Modified: pdfbox/trunk/pdfbox/src/main/java/org/apache/pdfbox/pdmodel/font/PDType1CFont.java
URL: http://svn.apache.org/viewvc/pdfbox/trunk/pdfbox/src/main/java/org/apache/pdfbox/pdmodel/font/PDType1CFont.java?rev=1900888&r1=1900887&r2=1900888&view=diff
==============================================================================
--- pdfbox/trunk/pdfbox/src/main/java/org/apache/pdfbox/pdmodel/font/PDType1CFont.java (original)
+++ pdfbox/trunk/pdfbox/src/main/java/org/apache/pdfbox/pdmodel/font/PDType1CFont.java Sat May 14 16:21:06 2022
@@ -35,6 +35,7 @@ import org.apache.fontbox.cff.CFFType1Fo
 import org.apache.fontbox.util.BoundingBox;
 import org.apache.pdfbox.cos.COSDictionary;
 import org.apache.pdfbox.cos.COSName;
+import org.apache.pdfbox.io.RandomAccessRead;
 import org.apache.pdfbox.pdmodel.common.PDRectangle;
 import org.apache.pdfbox.pdmodel.common.PDStream;
 import org.apache.pdfbox.pdmodel.font.encoding.Encoding;
@@ -76,17 +77,18 @@ public class PDType1CFont extends PDSimp
         super(fontDictionary);
 
         PDFontDescriptor fd = getFontDescriptor();
-        byte[] bytes = null;
+        RandomAccessRead randomAccessRead = null;
         if (fd != null)
         {
             PDStream ff3Stream = fd.getFontFile3();
             if (ff3Stream != null)
             {
-                bytes = ff3Stream.toByteArray();
-                if (bytes.length == 0)
+                randomAccessRead = fd.getFontFile3().getCOSObject().createView();
+                if (randomAccessRead.length() == 0)
                 {
                     LOG.error("Invalid data for embedded Type1C font " + getName());
-                    bytes = null;
+                    randomAccessRead.close();
+                    randomAccessRead = null;
                 }
             }
         }
@@ -95,11 +97,11 @@ public class PDType1CFont extends PDSimp
         CFFType1Font cffEmbedded = null;
         try
         {
-            if (bytes != null)
+            if (randomAccessRead != null)
             {
                 // note: this could be an OpenType file, fortunately CFFParser can handle that
                 CFFParser cffParser = new CFFParser();
-                CFFFont parsedCffFont = cffParser.parse(bytes, new FF3ByteSource()).get(0);
+                CFFFont parsedCffFont = cffParser.parse(randomAccessRead).get(0);
                 if (parsedCffFont instanceof CFFType1Font)
                 {
                     cffEmbedded = (CFFType1Font) parsedCffFont;
@@ -109,6 +111,7 @@ public class PDType1CFont extends PDSimp
                     LOG.error("Expected CFFType1Font, got " + parsedCffFont.getClass().getSimpleName());
                     fontIsDamaged = true;
                 }
+                randomAccessRead.close();
             }
         }
         catch (IOException e)
@@ -482,12 +485,4 @@ public class PDType1CFont extends PDSimp
         return ".notdef";
     }
     
-    private class FF3ByteSource implements CFFParser.ByteSource
-    {
-        @Override
-        public byte[] getBytes() throws IOException
-        {
-            return getFontDescriptor().getFontFile3().toByteArray();
-        }
-    }
 }