Author: tilman
Date: Tue Apr 15 15:15:09 2025
New Revision: 1925096

URL: http://svn.apache.org/viewvc?rev=1925096&view=rev
Log:
PDFBOX-5987: preprocess DIV commands

Modified:
    
pdfbox/branches/2.0/fontbox/src/main/java/org/apache/fontbox/cff/Type2CharString.java

Modified: 
pdfbox/branches/2.0/fontbox/src/main/java/org/apache/fontbox/cff/Type2CharString.java
URL: 
http://svn.apache.org/viewvc/pdfbox/branches/2.0/fontbox/src/main/java/org/apache/fontbox/cff/Type2CharString.java?rev=1925096&r1=1925095&r2=1925096&view=diff
==============================================================================
--- 
pdfbox/branches/2.0/fontbox/src/main/java/org/apache/fontbox/cff/Type2CharString.java
 (original)
+++ 
pdfbox/branches/2.0/fontbox/src/main/java/org/apache/fontbox/cff/Type2CharString.java
 Tue Apr 15 15:15:09 2025
@@ -82,6 +82,43 @@ public class Type2CharString extends Typ
     {
         type1Sequence = new ArrayList<Object>();
         pathCount = 0;
+
+        // PDFBOX-5987: the sequence contains several "num denom DIV" 
sequences whose results are used
+        // for further operations. However the converter only handles direct 
arguments properly,
+        // not arguments that are created at runtime on the stack. It's not 
possible to fix this
+        // by just copying the command codes because addAlternatingCurve / 
addCurve require
+        // switching the sequence of arguments.
+        // The solution below just replaces all "num denom DIV" sequences with 
its result.
+        // If more files with even more complex sequences appear we will have 
to get rid of the
+        // converter and implement a complete renderer like with type1 
charstrings.
+        List<Object> newSequence = new ArrayList<Object>(sequence.size());
+        for (int i = 0; i < sequence.size(); ++i)
+        {
+            Object obj = sequence.get(i);
+            if (obj instanceof CharStringCommand &&
+                
"div".equals(CharStringCommand.TYPE2_VOCABULARY.get(((CharStringCommand) 
obj).getKey())) &&
+                 i >= 2)
+            {
+                Object num = sequence.get(i - 2);
+                Object den = sequence.get(i - 1);
+                if (num instanceof Number && den instanceof Number)
+                {
+                    float f = ((Number) num).floatValue() / ((Number) 
den).floatValue();
+                    newSequence.remove(newSequence.size() - 1);
+                    newSequence.remove(newSequence.size() - 1);
+                    newSequence.add(f);
+                }
+                else
+                {
+                    newSequence.add(sequence.get(i)); // GIGO
+                }
+            }
+            else
+            {
+                newSequence.add(sequence.get(i));
+            }
+        }
+
         CharStringHandler handler = new CharStringHandler() {
             @Override
             public List<Number> handleCommand(List<Number> numbers, 
CharStringCommand command)
@@ -89,7 +126,7 @@ public class Type2CharString extends Typ
                 return Type2CharString.this.handleCommand(numbers, command);
             }
         };
-        handler.handleSequence(sequence);
+        handler.handleSequence(newSequence);
     }
 
     @SuppressWarnings(value = { "unchecked" })


Reply via email to