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/08 15:30:07 UTC

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

Author: lehmi
Date: Sun May  8 15:30:06 2022
New Revision: 1900695

URL: http://svn.apache.org/viewvc?rev=1900695&view=rev
Log:
PDFBOX-5143: use static instances of CharStringCommand to reduce memory footprint

Modified:
    pdfbox/trunk/fontbox/src/main/java/org/apache/fontbox/cff/CharStringCommand.java
    pdfbox/trunk/fontbox/src/main/java/org/apache/fontbox/cff/Type1CharString.java
    pdfbox/trunk/fontbox/src/main/java/org/apache/fontbox/cff/Type1CharStringParser.java
    pdfbox/trunk/fontbox/src/main/java/org/apache/fontbox/cff/Type2CharString.java
    pdfbox/trunk/fontbox/src/main/java/org/apache/fontbox/cff/Type2CharStringParser.java
    pdfbox/trunk/fontbox/src/test/java/org/apache/fontbox/cff/CharStringCommandTest.java

Modified: pdfbox/trunk/fontbox/src/main/java/org/apache/fontbox/cff/CharStringCommand.java
URL: http://svn.apache.org/viewvc/pdfbox/trunk/fontbox/src/main/java/org/apache/fontbox/cff/CharStringCommand.java?rev=1900695&r1=1900694&r2=1900695&view=diff
==============================================================================
--- pdfbox/trunk/fontbox/src/main/java/org/apache/fontbox/cff/CharStringCommand.java (original)
+++ pdfbox/trunk/fontbox/src/main/java/org/apache/fontbox/cff/CharStringCommand.java Sun May  8 15:30:06 2022
@@ -30,15 +30,104 @@ public class CharStringCommand
     private final Type1KeyWord type1KeyWord;
     private final Type2KeyWord type2KeyWord;
 
+    private static final Map<Integer, CharStringCommand> CHAR_STRING_COMMANDS = createMap();
+
+    public static final CharStringCommand COMMAND_CLOSEPATH = CharStringCommand
+            .getInstance(Key.CLOSEPATH.hashValue);
+    public static final CharStringCommand COMMAND_RLINETO = CharStringCommand
+            .getInstance(Key.RLINETO.hashValue);
+    public static final CharStringCommand COMMAND_HLINETO = CharStringCommand
+            .getInstance(Key.HLINETO.hashValue);
+    public static final CharStringCommand COMMAND_VLINETO = CharStringCommand
+            .getInstance(Key.VLINETO.hashValue);
+    public static final CharStringCommand COMMAND_RRCURVETO = CharStringCommand
+            .getInstance(Key.RRCURVETO.hashValue);
+    public static final CharStringCommand COMMAND_HSBW = CharStringCommand
+            .getInstance(Key.HSBW.hashValue);
+    public static final CharStringCommand COMMAND_CALLOTHERSUBR = CharStringCommand
+            .getInstance(Key.CALLOTHERSUBR.hashValue);
+
+    private static final int KEY_UNKNOWN = 99;
+    private static final CharStringCommand COMMAND_UNKNOWN = new CharStringCommand(KEY_UNKNOWN, 0);
+
+    private static Map<Integer, CharStringCommand> createMap()
+    {
+        Map<Integer, CharStringCommand> charStringCommandMap = new HashMap<>();
+        // one byte commands
+        charStringCommandMap.put(Key.HSTEM.hashValue, new CharStringCommand(Key.HSTEM));
+        charStringCommandMap.put(Key.VSTEM.hashValue, new CharStringCommand(Key.VSTEM));
+        charStringCommandMap.put(Key.VMOVETO.hashValue, new CharStringCommand(Key.VMOVETO));
+        charStringCommandMap.put(Key.RLINETO.hashValue, new CharStringCommand(Key.RLINETO));
+        charStringCommandMap.put(Key.HLINETO.hashValue, new CharStringCommand(Key.HLINETO));
+        charStringCommandMap.put(Key.VLINETO.hashValue, new CharStringCommand(Key.VLINETO));
+        charStringCommandMap.put(Key.RRCURVETO.hashValue, new CharStringCommand(Key.RRCURVETO));
+        charStringCommandMap.put(Key.CLOSEPATH.hashValue, new CharStringCommand(Key.CLOSEPATH));
+        charStringCommandMap.put(Key.CALLSUBR.hashValue, new CharStringCommand(Key.CALLSUBR));
+        charStringCommandMap.put(Key.RET.hashValue, new CharStringCommand(Key.RET));
+        charStringCommandMap.put(Key.ESCAPE.hashValue, new CharStringCommand(Key.ESCAPE));
+
+        charStringCommandMap.put(Key.HSBW.hashValue, new CharStringCommand(Key.HSBW));
+        charStringCommandMap.put(Key.ENDCHAR.hashValue, new CharStringCommand(Key.ENDCHAR));
+        charStringCommandMap.put(Key.HSTEMHM.hashValue, new CharStringCommand(Key.HSTEMHM));
+        charStringCommandMap.put(Key.HINTMASK.hashValue, new CharStringCommand(Key.HINTMASK));
+        charStringCommandMap.put(Key.CNTRMASK.hashValue, new CharStringCommand(Key.CNTRMASK));
+        charStringCommandMap.put(Key.RMOVETO.hashValue, new CharStringCommand(Key.RMOVETO));
+        charStringCommandMap.put(Key.HMOVETO.hashValue, new CharStringCommand(Key.HMOVETO));
+        charStringCommandMap.put(Key.VSTEMHM.hashValue, new CharStringCommand(Key.VSTEMHM));
+        charStringCommandMap.put(Key.RCURVELINE.hashValue, new CharStringCommand(Key.RCURVELINE));
+        charStringCommandMap.put(Key.RLINECURVE.hashValue, new CharStringCommand(Key.RLINECURVE));
+        charStringCommandMap.put(Key.VVCURVETO.hashValue, new CharStringCommand(Key.VVCURVETO));
+        charStringCommandMap.put(Key.HHCURVETO.hashValue, new CharStringCommand(Key.HHCURVETO));
+        charStringCommandMap.put(Key.SHORTINT.hashValue, new CharStringCommand(Key.SHORTINT));
+        charStringCommandMap.put(Key.CALLGSUBR.hashValue, new CharStringCommand(Key.CALLGSUBR));
+        charStringCommandMap.put(Key.VHCURVETO.hashValue, new CharStringCommand(Key.VHCURVETO));
+        charStringCommandMap.put(Key.HVCURVETO.hashValue, new CharStringCommand(Key.HVCURVETO));
+
+        // two byte commands
+        charStringCommandMap.put(Key.DOTSECTION.hashValue, new CharStringCommand(12, 0));
+        charStringCommandMap.put(Key.VSTEM3.hashValue, new CharStringCommand(12, 1));
+        charStringCommandMap.put(Key.HSTEM3.hashValue, new CharStringCommand(12, 2));
+        charStringCommandMap.put(Key.AND.hashValue, new CharStringCommand(12, 3));
+        charStringCommandMap.put(Key.OR.hashValue, new CharStringCommand(12, 4));
+        charStringCommandMap.put(Key.NOT.hashValue, new CharStringCommand(12, 5));
+        charStringCommandMap.put(Key.SEAC.hashValue, new CharStringCommand(12, 6));
+        charStringCommandMap.put(Key.SBW.hashValue, new CharStringCommand(12, 7));
+        charStringCommandMap.put(Key.ABS.hashValue, new CharStringCommand(12, 9));
+        charStringCommandMap.put(Key.ADD.hashValue, new CharStringCommand(12, 10));
+        charStringCommandMap.put(Key.SUB.hashValue, new CharStringCommand(12, 11));
+        charStringCommandMap.put(Key.DIV.hashValue, new CharStringCommand(12, 12));
+        charStringCommandMap.put(Key.NEG.hashValue, new CharStringCommand(12, 14));
+        charStringCommandMap.put(Key.EQ.hashValue, new CharStringCommand(12, 15));
+        charStringCommandMap.put(Key.CALLOTHERSUBR.hashValue, new CharStringCommand(12, 16));
+        charStringCommandMap.put(Key.POP.hashValue, new CharStringCommand(12, 17));
+        charStringCommandMap.put(Key.DROP.hashValue, new CharStringCommand(12, 18));
+        charStringCommandMap.put(Key.PUT.hashValue, new CharStringCommand(12, 20));
+        charStringCommandMap.put(Key.GET.hashValue, new CharStringCommand(12, 21));
+        charStringCommandMap.put(Key.IFELSE.hashValue, new CharStringCommand(12, 22));
+        charStringCommandMap.put(Key.RANDOM.hashValue, new CharStringCommand(12, 23));
+        charStringCommandMap.put(Key.MUL.hashValue, new CharStringCommand(12, 24));
+        charStringCommandMap.put(Key.SQRT.hashValue, new CharStringCommand(12, 26));
+        charStringCommandMap.put(Key.DUP.hashValue, new CharStringCommand(12, 27));
+        charStringCommandMap.put(Key.EXCH.hashValue, new CharStringCommand(12, 28));
+        charStringCommandMap.put(Key.INDEX.hashValue, new CharStringCommand(12, 29));
+        charStringCommandMap.put(Key.ROLL.hashValue, new CharStringCommand(12, 30));
+        charStringCommandMap.put(Key.SETCURRENTPOINT.hashValue, new CharStringCommand(12, 33));
+        charStringCommandMap.put(Key.HFLEX.hashValue, new CharStringCommand(12, 34));
+        charStringCommandMap.put(Key.FLEX.hashValue, new CharStringCommand(12, 35));
+        charStringCommandMap.put(Key.HFLEX1.hashValue, new CharStringCommand(12, 36));
+        charStringCommandMap.put(Key.FLEX1.hashValue, new CharStringCommand(12, 37));
+        return charStringCommandMap;
+    }
+
     /**
-     * Constructor with one value.
+     * Constructor with the CharStringCommand key as value.
      * 
-     * @param b0 value
+     * @param key the key of the char string command
      */
-    public CharStringCommand(int b0)
+    private CharStringCommand(CharStringCommand.Key key)
     {
-        type1KeyWord = Type1KeyWord.valueOfKey(b0);
-        type2KeyWord = Type2KeyWord.valueOfKey(b0);
+        type1KeyWord = Type1KeyWord.valueOfKey(key.hashValue);
+        type2KeyWord = Type2KeyWord.valueOfKey(key.hashValue);
     }
 
     /**
@@ -47,41 +136,84 @@ public class CharStringCommand
      * @param b0 value1
      * @param b1 value2
      */
-    public CharStringCommand(int b0, int b1)
+    private CharStringCommand(int b0, int b1)
     {
         type1KeyWord = Type1KeyWord.valueOfKey(b0, b1);
         type2KeyWord = Type2KeyWord.valueOfKey(b0, b1);
     }
 
+
+    /**
+     * Get an instance of the CharStringCommand represented by the given value.
+     * 
+     * @param b0 value
+     */
+    public static CharStringCommand getInstance(int b0)
+    {
+        CharStringCommand command = CHAR_STRING_COMMANDS.get(b0);
+        return command != null ? command : COMMAND_UNKNOWN;
+    }
+
+    /**
+     * Get an instance of the CharStringCommand represented by the given two values.
+     * 
+     * @param b0 value1
+     * @param b1 value2
+     */
+    public static CharStringCommand getInstance(int b0, int b1)
+    {
+        CharStringCommand command = CHAR_STRING_COMMANDS.get(getKeyHashValue(b0, b1));
+        return command != null ? command : COMMAND_UNKNOWN;
+    }
+
     /**
-     * Constructor with an array as values.
+     * Get an instance of the CharStringCommand represented by the given array.
      * 
      * @param values array of values
      */
-    public CharStringCommand(int[] values)
+    public static CharStringCommand getInstance(int[] values)
     {
         if (values.length == 1)
         {
-            type1KeyWord = Type1KeyWord.valueOfKey(values[0]);
-            type2KeyWord = Type2KeyWord.valueOfKey(values[0]);
+            return getInstance(values[0]);
         }
         else if (values.length == 2)
         {
-            type1KeyWord = Type1KeyWord.valueOfKey(values[0], values[1]);
-            type2KeyWord = Type2KeyWord.valueOfKey(values[0], values[1]);
+            return getInstance(values[0], values[1]);
+        }
+        return COMMAND_UNKNOWN;
+    }
+
+    private static int getKeyHashValue(int b0, int b1)
+    {
+        Type1KeyWord type1Key = Type1KeyWord.valueOfKey(b0, b1);
+        if (type1Key != null)
+        {
+            return type1Key.key.hashValue;
         }
-        else
+        Type2KeyWord type2Key = Type2KeyWord.valueOfKey(b0, b1);
+        if (type2Key != null)
         {
-            type1KeyWord = null;
-            type2KeyWord = null;
+            return type2Key.key.hashValue;
         }
+        return KEY_UNKNOWN;
     }
 
+    /**
+     * Return the underlying type1 key word.
+     * 
+     * @return the type1 key word
+     */
     public Type1KeyWord getType1KeyWord()
     {
         return type1KeyWord;
     }
 
+    /**
+     * Return the underlying type2 key word.
+     * 
+     * @return the type2 key word
+     */
     public Type2KeyWord getType2KeyWord()
     {
         return type2KeyWord;

Modified: pdfbox/trunk/fontbox/src/main/java/org/apache/fontbox/cff/Type1CharString.java
URL: http://svn.apache.org/viewvc/pdfbox/trunk/fontbox/src/main/java/org/apache/fontbox/cff/Type1CharString.java?rev=1900695&r1=1900694&r2=1900695&view=diff
==============================================================================
--- pdfbox/trunk/fontbox/src/main/java/org/apache/fontbox/cff/Type1CharString.java (original)
+++ pdfbox/trunk/fontbox/src/main/java/org/apache/fontbox/cff/Type1CharString.java Sun May  8 15:30:06 2022
@@ -50,8 +50,8 @@ public class Type1CharString
     private Point2D.Float current = null;
     private boolean isFlex = false;
     private final List<Point2D.Float> flexPoints = new ArrayList<>();
-    protected List<Object> type1Sequence;
-    protected int commandCount = 0;
+    private final List<Object> type1Sequence = new ArrayList<>();
+    private int commandCount = 0;
 
     /**
      * Constructs a new Type1CharString object.
@@ -62,10 +62,10 @@ public class Type1CharString
      * @param sequence Type 1 char string sequence
      */
     public Type1CharString(Type1CharStringReader font, String fontName, String glyphName,
-                           List<Object> sequence)
+            List<Object> sequence)
     {
         this(font, fontName, glyphName);
-        type1Sequence = sequence;
+        type1Sequence.addAll(sequence);
     }
 
     /**
@@ -499,6 +499,18 @@ public class Type1CharString
         }
     }
 
+    /**
+     * Add a command to the type1 sequence.
+     * 
+     * @param numbers the parameters of the command to be added
+     * @param command the command to be added
+     */
+    protected void addCommand(List<Number> numbers, CharStringCommand command)
+    {
+        type1Sequence.addAll(numbers);
+        type1Sequence.add(command);
+    }
+
     @Override
     public String toString()
     {

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=1900695&r1=1900694&r2=1900695&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 Sun May  8 15:30:06 2022
@@ -157,12 +157,12 @@ public class Type1CharStringParser
             sequence.remove(sequence.size() - 1);
             // end flex
             sequence.add(0);
-            sequence.add(new CharStringCommand(TWO_BYTE, CALLOTHERSUBR));
+            sequence.add(CharStringCommand.COMMAND_CALLOTHERSUBR);
             break;
         case 1:
             // begin flex
             sequence.add(1);
-            sequence.add(new CharStringCommand(TWO_BYTE, CALLOTHERSUBR));
+            sequence.add(CharStringCommand.COMMAND_CALLOTHERSUBR);
             break;
         case 3:
             // allows hint replacement
@@ -218,9 +218,9 @@ public class Type1CharStringParser
         if (b0 == 12)
         {
             int b1 = input.readUnsignedByte();
-            return new CharStringCommand(b0, b1);
+            return CharStringCommand.getInstance(b0, b1);
         }
-        return new CharStringCommand(b0);
+        return CharStringCommand.getInstance(b0);
     }
 
     private Integer readNumber(DataInput input, int b0) throws IOException

Modified: pdfbox/trunk/fontbox/src/main/java/org/apache/fontbox/cff/Type2CharString.java
URL: http://svn.apache.org/viewvc/pdfbox/trunk/fontbox/src/main/java/org/apache/fontbox/cff/Type2CharString.java?rev=1900695&r1=1900694&r2=1900695&view=diff
==============================================================================
--- pdfbox/trunk/fontbox/src/main/java/org/apache/fontbox/cff/Type2CharString.java (original)
+++ pdfbox/trunk/fontbox/src/main/java/org/apache/fontbox/cff/Type2CharString.java Sun May  8 15:30:06 2022
@@ -21,6 +21,7 @@ import java.util.Arrays;
 import java.util.Collections;
 import java.util.List;
 
+import org.apache.fontbox.cff.CharStringCommand.Type1KeyWord;
 import org.apache.fontbox.cff.CharStringCommand.Type2KeyWord;
 import org.apache.fontbox.type1.Type1CharStringReader;
 
@@ -71,7 +72,6 @@ public class Type2CharString extends Typ
      */
     private void convertType1ToType2(List<Object> sequence)
     {
-        type1Sequence = new ArrayList<>();
         pathCount = 0;
         CharStringHandler handler = Type2CharString.this::handleType2Command;
         handler.handleSequence(sequence);
@@ -79,7 +79,6 @@ public class Type2CharString extends Typ
 
     private List<Number> handleType2Command(List<Number> numbers, CharStringCommand command)
     {
-        commandCount++;
         Type2KeyWord type2KeyWord = command.getType2KeyWord();
         if (type2KeyWord == null)
         {
@@ -121,7 +120,7 @@ public class Type2CharString extends Typ
             {
                 // deprecated "seac" operator
                 numbers.add(0, 0);
-                addCommand(numbers, new CharStringCommand(12, 6));
+                addCommand(numbers, CharStringCommand.getInstance(12, 6));
             }
             else
             {
@@ -144,14 +143,14 @@ public class Type2CharString extends Typ
                         numbers.get(3), 0);
                 List<Number> second = Arrays.asList(numbers.get(4), 0, numbers.get(5),
                         -(numbers.get(2).floatValue()), numbers.get(6), 0);
-                addCommandList(Arrays.asList(first, second), new CharStringCommand(8));
+                addCommandList(Arrays.asList(first, second), CharStringCommand.COMMAND_RRCURVETO);
             }
             break;
         case FLEX:
         {
             List<Number> first = numbers.subList(0, 6);
             List<Number> second = numbers.subList(6, 12);
-            addCommandList(Arrays.asList(first, second), new CharStringCommand(8));
+            addCommandList(Arrays.asList(first, second), CharStringCommand.COMMAND_RRCURVETO);
             break;
         }
         case HFLEX1:
@@ -161,7 +160,7 @@ public class Type2CharString extends Typ
                         numbers.get(3), numbers.get(4), 0);
                 List<Number> second = Arrays.asList(numbers.get(5), 0, numbers.get(6), numbers.get(7),
                         numbers.get(8), 0);
-                addCommandList(Arrays.asList(first, second), new CharStringCommand(8));
+                addCommandList(Arrays.asList(first, second), CharStringCommand.COMMAND_RRCURVETO);
             }
             break;
         case FLEX1:
@@ -177,25 +176,26 @@ public class Type2CharString extends Typ
             List<Number> second = Arrays.asList(numbers.get(6), numbers.get(7), numbers.get(8),
                     numbers.get(9), (Math.abs(dx) > Math.abs(dy) ? numbers.get(10) : -dx),
                     (Math.abs(dx) > Math.abs(dy) ? -dy : numbers.get(10)));
-            addCommandList(Arrays.asList(first, second), new CharStringCommand(8));
+            addCommandList(Arrays.asList(first, second),
+                    CharStringCommand.COMMAND_RRCURVETO);
             break;
         }
         case RCURVELINE:
             if (numbers.size() >= 2)
             {
                 addCommandList(split(numbers.subList(0, numbers.size() - 2), 6),
-                        new CharStringCommand(8));
+                        CharStringCommand.COMMAND_RRCURVETO);
                 addCommand(numbers.subList(numbers.size() - 2, numbers.size()),
-                        new CharStringCommand(5));
+                        CharStringCommand.COMMAND_RLINETO);
             }
             break;
         case RLINECURVE:
             if (numbers.size() >= 6)
             {
                 addCommandList(split(numbers.subList(0, numbers.size() - 6), 2),
-                        new CharStringCommand(5));
+                        CharStringCommand.COMMAND_RLINETO);
                 addCommand(numbers.subList(numbers.size() - 6, numbers.size()),
-                        new CharStringCommand(8));
+                        CharStringCommand.COMMAND_RRCURVETO);
             }
             break;
         case HHCURVETO:
@@ -211,17 +211,17 @@ public class Type2CharString extends Typ
 
     private List<Number> clearStack(List<Number> numbers, boolean flag)
     {
-        if (type1Sequence.isEmpty())
+        if (getType1Sequence().isEmpty())
         {
             if (flag)
             {
                 addCommand(Arrays.asList(0, numbers.get(0).floatValue() + nominalWidthX),
-                        new CharStringCommand(13));
+                        CharStringCommand.COMMAND_HSBW);
                 numbers = numbers.subList(1, numbers.size());
             }
             else
             {
-                addCommand(Arrays.asList(0, defWidthX), new CharStringCommand(13));
+                addCommand(Arrays.asList(0, defWidthX), CharStringCommand.COMMAND_HSBW);
             }
         }
         return numbers;
@@ -247,14 +247,11 @@ public class Type2CharString extends Typ
 
     private void closeCharString2Path()
     {
-        CharStringCommand command = pathCount > 0 ? (CharStringCommand) type1Sequence
-                .get(type1Sequence.size() - 1)
-                : null;
-
-        CharStringCommand closepathCommand = new CharStringCommand(9);
-        if (command != null && !closepathCommand.equals(command))
+        CharStringCommand command = pathCount > 0
+                ? (CharStringCommand) getType1Sequence().get(getType1Sequence().size() - 1) : null;
+        if (command != null && command.getType1KeyWord() != Type1KeyWord.CLOSEPATH)
         {
-            addCommand(Collections.<Number> emptyList(), closepathCommand);
+            addCommand(Collections.<Number> emptyList(), CharStringCommand.COMMAND_CLOSEPATH);
         }
     }
 
@@ -262,8 +259,8 @@ public class Type2CharString extends Typ
     {
         while (!numbers.isEmpty())
         {
-            addCommand(numbers.subList(0, 1), new CharStringCommand(
-                    horizontal ? 6 : 7));
+            addCommand(numbers.subList(0, 1), horizontal ? CharStringCommand.COMMAND_HLINETO
+                    : CharStringCommand.COMMAND_VLINETO);
             numbers = numbers.subList(1, numbers.size());
             horizontal = !horizontal;
         }
@@ -279,14 +276,14 @@ public class Type2CharString extends Typ
                 addCommand(Arrays.asList(numbers.get(0), 0,
                         numbers.get(1), numbers.get(2), last ? numbers.get(4)
                                 : 0, numbers.get(3)),
-                        new CharStringCommand(8));
+                        CharStringCommand.COMMAND_RRCURVETO);
             } 
             else
             {
                 addCommand(Arrays.asList(0, numbers.get(0),
                         numbers.get(1), numbers.get(2), numbers.get(3),
                         last ? numbers.get(4) : 0),
-                        new CharStringCommand(8));
+                        CharStringCommand.COMMAND_RRCURVETO);
             }
             numbers = numbers.subList(last ? 5 : 4, numbers.size());
             horizontal = !horizontal;
@@ -305,14 +302,14 @@ public class Type2CharString extends Typ
                         first ? numbers.get(0) : 0, numbers
                                 .get(first ? 2 : 1),
                         numbers.get(first ? 3 : 2), numbers.get(first ? 4 : 3),
-                        0), new CharStringCommand(8));
+                        0), CharStringCommand.COMMAND_RRCURVETO);
             } 
             else
             {
                 addCommand(Arrays.asList(first ? numbers.get(0) : 0, numbers.get(first ? 1 : 0), numbers
                         .get(first ? 2 : 1), numbers.get(first ? 3 : 2),
                         0, numbers.get(first ? 4 : 3)),
-                        new CharStringCommand(8));
+                        CharStringCommand.COMMAND_RRCURVETO);
             }
             numbers = numbers.subList(first ? 5 : 4, numbers.size());
         }
@@ -323,12 +320,6 @@ public class Type2CharString extends Typ
         numbers.forEach(ns -> addCommand(ns, command));
     }
 
-    private void addCommand(List<Number> numbers, CharStringCommand command)
-    {
-        type1Sequence.addAll(numbers);
-        type1Sequence.add(command);
-    }
-
     private static <E> List<List<E>> split(List<E> list, int size)
     {
         int listSize = list.size() / size;

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=1900695&r1=1900694&r2=1900695&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 Sun May  8 15:30:06 2022
@@ -172,7 +172,7 @@ public class Type2CharStringParser
         {
             int b1 = input.readUnsignedByte();
 
-            return new CharStringCommand(b0, b1);
+            return CharStringCommand.getInstance(b0, b1);
         } 
         else if (b0 == 19 || b0 == 20)
         {
@@ -184,10 +184,10 @@ public class Type2CharStringParser
                 value[i] = input.readUnsignedByte();
             }
 
-            return new CharStringCommand(value);
+            return CharStringCommand.getInstance(value);
         }
 
-        return new CharStringCommand(b0);
+        return CharStringCommand.getInstance(b0);
     }
 
     private Number readNumber(int b0, DataInput input) throws IOException

Modified: pdfbox/trunk/fontbox/src/test/java/org/apache/fontbox/cff/CharStringCommandTest.java
URL: http://svn.apache.org/viewvc/pdfbox/trunk/fontbox/src/test/java/org/apache/fontbox/cff/CharStringCommandTest.java?rev=1900695&r1=1900694&r2=1900695&view=diff
==============================================================================
--- pdfbox/trunk/fontbox/src/test/java/org/apache/fontbox/cff/CharStringCommandTest.java (original)
+++ pdfbox/trunk/fontbox/src/test/java/org/apache/fontbox/cff/CharStringCommandTest.java Sun May  8 15:30:06 2022
@@ -41,18 +41,18 @@ class CharStringCommandTest
     @Test
     void testCharStringCommand()
     {
-        CharStringCommand charStringCommand1 = new CharStringCommand(1);
+        CharStringCommand charStringCommand1 = CharStringCommand.getInstance(1);
         assertEquals(Type1KeyWord.HSTEM, charStringCommand1.getType1KeyWord());
         assertEquals(Type2KeyWord.HSTEM, charStringCommand1.getType2KeyWord());
         assertEquals("HSTEM|", charStringCommand1.toString());
 
-        CharStringCommand charStringCommand12_0 = new CharStringCommand(12, 0);
+        CharStringCommand charStringCommand12_0 = CharStringCommand.getInstance(12, 0);
         assertEquals(Type1KeyWord.DOTSECTION, charStringCommand12_0.getType1KeyWord());
         assertNull(charStringCommand12_0.getType2KeyWord());
         assertEquals("DOTSECTION|", charStringCommand12_0.toString());
 
         int[] values12_3 = new int[] { 12, 3 };
-        CharStringCommand charStringCommand12_3 = new CharStringCommand(values12_3);
+        CharStringCommand charStringCommand12_3 = CharStringCommand.getInstance(values12_3);
         assertNull(charStringCommand12_3.getType1KeyWord());
         assertEquals(Type2KeyWord.AND, charStringCommand12_3.getType2KeyWord());
         assertEquals("AND|", charStringCommand12_3.toString());
@@ -62,7 +62,7 @@ class CharStringCommandTest
     @Test
     void testUnknownCharStringCommand()
     {
-        CharStringCommand charStringCommandUnknown = new CharStringCommand(99);
+        CharStringCommand charStringCommandUnknown = CharStringCommand.getInstance(99);
         assertEquals("unknown command|", charStringCommandUnknown.toString());
     }