Author: lehmi
Date: Sat Mar 28 08:52:53 2026
New Revision: 1932604

Log:
PDFBOX-6175: store cid ranges more compact based on a proposal by Kiyotsuki 
Suzuki

Modified:
   
pdfbox/trunk/pdfbox/src/main/java/org/apache/pdfbox/pdmodel/font/PDCIDFont.java

Modified: 
pdfbox/trunk/pdfbox/src/main/java/org/apache/pdfbox/pdmodel/font/PDCIDFont.java
==============================================================================
--- 
pdfbox/trunk/pdfbox/src/main/java/org/apache/pdfbox/pdmodel/font/PDCIDFont.java 
    Sat Mar 28 08:30:16 2026        (r1932603)
+++ 
pdfbox/trunk/pdfbox/src/main/java/org/apache/pdfbox/pdmodel/font/PDCIDFont.java 
    Sat Mar 28 08:52:53 2026        (r1932604)
@@ -18,7 +18,9 @@ package org.apache.pdfbox.pdmodel.font;
 
 import java.io.IOException;
 import java.io.InputStream;
+import java.util.ArrayList;
 import java.util.HashMap;
+import java.util.List;
 import java.util.Map;
 import org.apache.logging.log4j.Logger;
 import org.apache.logging.log4j.LogManager;
@@ -47,12 +49,17 @@ public abstract class PDCIDFont implemen
 
     protected final PDType0Font parent;
 
-    private Map<Integer, Float> widths;
+    private final Map<Integer, Float> widths = new HashMap<>();
     private float defaultWidth;
     private float averageWidth;
 
-    private final Map<Integer, Float> verticalDisplacementY = new HashMap<>(); 
// w1y
-    private final Map<Integer, Vector> positionVectors = new HashMap<>();     
// v
+    // vertical displacement, individual values
+    private final Map<Integer, Float> verticalDisplacementY = new HashMap<>();
+    // position vectors, individual values
+    private final Map<Integer, Vector> positionVectors = new HashMap<>();
+    // cid-ranges for verticalDisplacements and positionVectors
+    private final List<VerticalDisplacementRange> displacementRanges = new 
ArrayList<>();
+
     private final float[] dw2 = { 880, -1000 };
 
     protected final COSDictionary dict;
@@ -74,7 +81,6 @@ public abstract class PDCIDFont implemen
     private void readWidths()
     {
         // see 9.7.4.3, "Glyph Metrics in CIDFonts"
-        widths = new HashMap<>();
         COSArray wArray = dict.getCOSArray(COSName.W);
         if (wArray != null)
         {
@@ -181,11 +187,8 @@ public abstract class PDCIDFont implemen
                     COSNumber w1y = (COSNumber) w2Array.getObject(++i);
                     COSNumber v1x = (COSNumber) w2Array.getObject(++i);
                     COSNumber v1y = (COSNumber) w2Array.getObject(++i);
-                    for (int cid = first; cid <= last; cid++)
-                    {
-                        verticalDisplacementY.put(cid, w1y.floatValue());
-                        positionVectors.put(cid, new Vector(v1x.floatValue(), 
v1y.floatValue()));
-                    }
+                    displacementRanges.add(new 
VerticalDisplacementRange(first, last,
+                            new Vector(v1x.floatValue(), v1y.floatValue()), 
w1y.floatValue()));
                 }
             }
         }
@@ -292,7 +295,17 @@ public abstract class PDCIDFont implemen
         Vector v = positionVectors.get(cid);
         if (v == null)
         {
-            v = getDefaultPositionVector(cid);
+            VerticalDisplacementRange vdRange = displacementRanges.stream() //
+                    .filter(vdr -> vdr.rangeMatches(cid)) //
+                    .findFirst().orElse(null);
+            if (vdRange != null)
+            {
+                v = vdRange.getPositionVector();
+            }
+            else
+            {
+                v = getDefaultPositionVector(cid);
+            }
         }
         return v;
     }
@@ -309,7 +322,17 @@ public abstract class PDCIDFont implemen
         Float w1y = verticalDisplacementY.get(cid);
         if (w1y == null)
         {
-            w1y = dw2[1];
+            VerticalDisplacementRange vdRange = displacementRanges.stream() //
+                    .filter(vdr -> vdr.rangeMatches(cid)) //
+                    .findFirst().orElse(null);
+            if (vdRange != null)
+            {
+                w1y = vdRange.getVerticalDisplacement();
+            }
+            else
+            {
+                w1y = dw2[1];
+            }
         }
         return w1y;
     }
@@ -331,7 +354,7 @@ public abstract class PDCIDFont implemen
         {
             float totalWidths = 0.0f;
             int characterCount = 0;
-            if (widths != null)
+            if (!widths.isEmpty())
             {
                 for (Float width : widths.values())
                 {
@@ -417,4 +440,35 @@ public abstract class PDCIDFont implemen
         }
         return cid2gid;
     }
+
+    private static class VerticalDisplacementRange
+    {
+        final int rangeStart;
+        final int rangeEnd;
+        final Vector positionVector;
+        final float verticalDisplacment;
+
+        public VerticalDisplacementRange(int start, int end, Vector vector, 
float displacement)
+        {
+            rangeStart = start;
+            rangeEnd = end;
+            positionVector = vector;
+            verticalDisplacment = displacement;
+        }
+
+        public boolean rangeMatches(int value)
+        {
+            return value >= rangeStart && value <= rangeEnd;
+        }
+
+        public Vector getPositionVector()
+        {
+            return positionVector;
+        }
+
+        public float getVerticalDisplacement()
+        {
+            return verticalDisplacment;
+        }
+    }
 }

Reply via email to