Author: lehmi
Date: Sun Aug  2 15:58:22 2026
New Revision: 1936798

Log:
PDFBOX-6175: enable caching for the FontDecriptor of a Type0 font

Modified:
   pdfbox/trunk/pdfbox/src/main/java/org/apache/pdfbox/pdmodel/PDPage.java
   
pdfbox/trunk/pdfbox/src/main/java/org/apache/pdfbox/pdmodel/font/PDCIDFont.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/PDCIDFontType2.java
   
pdfbox/trunk/pdfbox/src/main/java/org/apache/pdfbox/pdmodel/font/PDCIDFontType2Embedder.java
   
pdfbox/trunk/pdfbox/src/main/java/org/apache/pdfbox/pdmodel/font/PDFontFactory.java
   
pdfbox/trunk/pdfbox/src/main/java/org/apache/pdfbox/pdmodel/font/PDType0Font.java

Modified: 
pdfbox/trunk/pdfbox/src/main/java/org/apache/pdfbox/pdmodel/PDPage.java
==============================================================================
--- pdfbox/trunk/pdfbox/src/main/java/org/apache/pdfbox/pdmodel/PDPage.java     
Sun Aug  2 10:59:48 2026        (r1936797)
+++ pdfbox/trunk/pdfbox/src/main/java/org/apache/pdfbox/pdmodel/PDPage.java     
Sun Aug  2 15:58:22 2026        (r1936798)
@@ -168,13 +168,28 @@ public class PDPage implements COSObject
                     {
                         resourceCache.removeCIDFont((COSObject) 
descendantFontBaseObject);
                     }
+                    // the font descriptor of a type0 font is part of the 
descendant font not of the parent font
+                    COSBase descFont = descendantFonts.getObject(0);
+                    if (descFont instanceof COSDictionary)
+                    {
+                        COSObject fdIndirectObject = ((COSDictionary) descFont)
+                                .getCOSObject(COSName.FONT_DESC);
+                        // remove PDFontDescriptor from cache
+                        if (fdIndirectObject != null)
+                        {
+                            
resourceCache.removeFontDescriptor(fdIndirectObject);
+                        }
+                    }
                 }
             }
-            COSObject fdIndirectObject = 
fontDict.getCOSObject(COSName.FONT_DESC);
-            // remove PDFontDescriptor from cache
-            if (fdIndirectObject != null)
+            else
             {
-                resourceCache.removeFontDescriptor(fdIndirectObject);
+                COSObject fdIndirectObject = 
fontDict.getCOSObject(COSName.FONT_DESC);
+                // remove PDFontDescriptor from cache
+                if (fdIndirectObject != null)
+                {
+                    resourceCache.removeFontDescriptor(fdIndirectObject);
+                }
             }
         }
         for (COSObject cosObject : getIndirectResourceObjects(resources, 
COSName.XOBJECT))

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 
    Sun Aug  2 10:59:48 2026        (r1936797)
+++ 
pdfbox/trunk/pdfbox/src/main/java/org/apache/pdfbox/pdmodel/font/PDCIDFont.java 
    Sun Aug  2 15:58:22 2026        (r1936798)
@@ -32,7 +32,9 @@ import org.apache.pdfbox.cos.COSBase;
 import org.apache.pdfbox.cos.COSDictionary;
 import org.apache.pdfbox.cos.COSName;
 import org.apache.pdfbox.cos.COSNumber;
+import org.apache.pdfbox.cos.COSObject;
 import org.apache.pdfbox.cos.COSStream;
+import org.apache.pdfbox.pdmodel.ResourceCache;
 import org.apache.pdfbox.pdmodel.common.COSObjectable;
 import org.apache.pdfbox.util.Matrix;
 import org.apache.pdfbox.util.Vector;
@@ -66,18 +68,40 @@ public abstract class PDCIDFont implemen
     protected boolean isEmbedded;
     protected boolean isDamaged;
 
-    private PDFontDescriptor fontDescriptor;
+    private final PDFontDescriptor fontDescriptor;
 
     /**
      * Constructor.
      *
      * @param fontDictionary The font dictionary according to the PDF 
specification.
+     * @param resourceCache ResourceCache, can be null.
+     * 
      */
-    PDCIDFont(COSDictionary fontDictionary)
+    PDCIDFont(COSDictionary fontDictionary, ResourceCache resourceCache)
     {
         this.dict = fontDictionary;
         readWidths();
         readVerticalDisplacements();
+        
+        PDFontDescriptor fd = null;
+        COSObject fdIndirectObject = dict.getCOSObject(COSName.FONT_DESC);
+        if (fdIndirectObject != null && resourceCache != null)
+        {
+            fd = resourceCache.getFontDescriptor(fdIndirectObject);
+        }
+        if (fd == null)
+        {
+            COSDictionary fdDict = dict.getCOSDictionary(COSName.FONT_DESC);
+            if (fdDict != null)
+            {
+                fd = new PDFontDescriptor(fdDict);
+                if (resourceCache != null && fdIndirectObject != null)
+                {
+                    resourceCache.put(fdIndirectObject, fd);
+                }
+            }
+        }
+        fontDescriptor = fd;
     }
 
     private void readWidths()
@@ -219,14 +243,6 @@ public abstract class PDCIDFont implemen
      */
     public PDFontDescriptor getFontDescriptor()
     {
-        if (fontDescriptor == null)
-        {
-            COSDictionary fd = dict.getCOSDictionary(COSName.FONT_DESC);
-            if (fd != null)
-            {
-                fontDescriptor = new PDFontDescriptor(fd);
-            }
-        }
         return fontDescriptor;
     }
 

Modified: 
pdfbox/trunk/pdfbox/src/main/java/org/apache/pdfbox/pdmodel/font/PDCIDFontType0.java
==============================================================================
--- 
pdfbox/trunk/pdfbox/src/main/java/org/apache/pdfbox/pdmodel/font/PDCIDFontType0.java
        Sun Aug  2 10:59:48 2026        (r1936797)
+++ 
pdfbox/trunk/pdfbox/src/main/java/org/apache/pdfbox/pdmodel/font/PDCIDFontType0.java
        Sun Aug  2 15:58:22 2026        (r1936798)
@@ -34,6 +34,7 @@ import org.apache.fontbox.cff.Type2CharS
 import org.apache.fontbox.util.BoundingBox;
 import org.apache.pdfbox.cos.COSDictionary;
 import org.apache.pdfbox.io.RandomAccessRead;
+import org.apache.pdfbox.pdmodel.ResourceCache;
 import org.apache.pdfbox.pdmodel.common.PDRectangle;
 import org.apache.pdfbox.pdmodel.common.PDStream;
 import org.apache.pdfbox.util.Matrix;
@@ -65,12 +66,14 @@ public class PDCIDFontType0 extends PDCI
      * Constructor.
      * 
      * @param fontDictionary The font dictionary according to the PDF 
specification.
+     * @param resourceCache ResourceCache, can be null.
      * 
      * @throws IOException if the font could not be read
      */
-    public PDCIDFontType0(COSDictionary fontDictionary) throws IOException
+    public PDCIDFontType0(COSDictionary fontDictionary, ResourceCache 
resourceCache)
+            throws IOException
     {
-        super(fontDictionary);
+        super(fontDictionary, resourceCache);
 
         boolean fontIsDamaged = false;
         CFFFont cffFont = null;
@@ -122,9 +125,8 @@ public class PDCIDFontType0 extends PDCI
         else
         {
             // find font or substitute
-            CIDFontMapping mapping = FontMappers.instance()
-                                                .getCIDFont(getBaseFont(), 
getFontDescriptor(),
-                                                            
getCIDSystemInfo());
+            CIDFontMapping mapping = 
FontMappers.instance().getCIDFont(getBaseFont(), fd,
+                    getCIDSystemInfo());
             FontBoxFont font;
             if (mapping.isCIDFont())
             {
@@ -211,7 +213,8 @@ public class PDCIDFontType0 extends PDCI
 
     private BoundingBox generateBoundingBox()
     {
-        if (getFontDescriptor() != null) {
+        if (getFontDescriptor() != null)
+        {
             PDRectangle bbox = getFontDescriptor().getFontBoundingBox();
             if (bbox != null && (Float.compare(bbox.getLowerLeftX(),0) != 0 ||
                 Float.compare(bbox.getLowerLeftY(),0) != 0 ||

Modified: 
pdfbox/trunk/pdfbox/src/main/java/org/apache/pdfbox/pdmodel/font/PDCIDFontType2.java
==============================================================================
--- 
pdfbox/trunk/pdfbox/src/main/java/org/apache/pdfbox/pdmodel/font/PDCIDFontType2.java
        Sun Aug  2 10:59:48 2026        (r1936797)
+++ 
pdfbox/trunk/pdfbox/src/main/java/org/apache/pdfbox/pdmodel/font/PDCIDFontType2.java
        Sun Aug  2 15:58:22 2026        (r1936798)
@@ -37,6 +37,7 @@ import org.apache.fontbox.ttf.TrueTypeFo
 import org.apache.fontbox.util.BoundingBox;
 import org.apache.pdfbox.cos.COSDictionary;
 import org.apache.pdfbox.io.RandomAccessRead;
+import org.apache.pdfbox.pdmodel.ResourceCache;
 import org.apache.pdfbox.pdmodel.common.PDRectangle;
 import org.apache.pdfbox.pdmodel.common.PDStream;
 import org.apache.pdfbox.util.Matrix;
@@ -62,11 +63,14 @@ public class PDCIDFontType2 extends PDCI
      * Constructor.
      * 
      * @param fontDictionary The font dictionary according to the PDF 
specification.
+     * @param resourceCache ResourceCache, can be null.
+     * 
      * @throws IOException if the font could not be read
      */
-    public PDCIDFontType2(COSDictionary fontDictionary) throws IOException
+    public PDCIDFontType2(COSDictionary fontDictionary, ResourceCache 
resourceCache)
+            throws IOException
     {
-        this(fontDictionary, null);
+        this(fontDictionary, null, resourceCache);
     }
     
     /**
@@ -74,14 +78,14 @@ public class PDCIDFontType2 extends PDCI
      * 
      * @param fontDictionary The font dictionary according to the PDF 
specification.
      * @param trueTypeFont The true type font used to create the parent font
+     * @param resourceCache ResourceCache, can be null.
+     * 
      * @throws IOException if the font could not be read
      */
-    public PDCIDFontType2(COSDictionary fontDictionary, TrueTypeFont 
trueTypeFont)
-            throws IOException
+    public PDCIDFontType2(COSDictionary fontDictionary, TrueTypeFont 
trueTypeFont,
+            ResourceCache resourceCache) throws IOException
     {
-        super(fontDictionary);
-
-        PDFontDescriptor fd = getFontDescriptor();
+        super(fontDictionary, resourceCache);
         if (trueTypeFont != null)
         {
             ttf = trueTypeFont;
@@ -95,8 +99,8 @@ public class PDCIDFontType2 extends PDCI
         {
             boolean fontIsDamaged = false;
             TrueTypeFont ttfFont = null;
-            
             PDStream stream = null;
+            PDFontDescriptor fd = getFontDescriptor();
             if (fd != null)
             {
                 stream = fd.getFontFile2();
@@ -155,9 +159,8 @@ public class PDCIDFontType2 extends PDCI
     {
         TrueTypeFont ttfFont;
 
-        CIDFontMapping mapping = FontMappers.instance()
-                .getCIDFont(getBaseFont(), getFontDescriptor(),
-                        getCIDSystemInfo());
+        CIDFontMapping mapping = 
FontMappers.instance().getCIDFont(getBaseFont(),
+                getFontDescriptor(), getCIDSystemInfo());
         if (mapping.isCIDFont())
         {
             ttfFont = mapping.getFont();
@@ -350,6 +353,7 @@ public class PDCIDFontType2 extends PDCI
         return width;
     }
 
+    @Override
     protected byte[] encode(int unicode, PDType0Font parent)
     {
         int cid = -1;

Modified: 
pdfbox/trunk/pdfbox/src/main/java/org/apache/pdfbox/pdmodel/font/PDCIDFontType2Embedder.java
==============================================================================
--- 
pdfbox/trunk/pdfbox/src/main/java/org/apache/pdfbox/pdmodel/font/PDCIDFontType2Embedder.java
        Sun Aug  2 10:59:48 2026        (r1936797)
+++ 
pdfbox/trunk/pdfbox/src/main/java/org/apache/pdfbox/pdmodel/font/PDCIDFontType2Embedder.java
        Sun Aug  2 15:58:22 2026        (r1936798)
@@ -733,6 +733,6 @@ final class PDCIDFontType2Embedder exten
      */
     public PDCIDFont getCIDFont() throws IOException
     {
-        return new PDCIDFontType2(cidFont, ttf);
+        return new PDCIDFontType2(cidFont, ttf, null);
     }
 }

Modified: 
pdfbox/trunk/pdfbox/src/main/java/org/apache/pdfbox/pdmodel/font/PDFontFactory.java
==============================================================================
--- 
pdfbox/trunk/pdfbox/src/main/java/org/apache/pdfbox/pdmodel/font/PDFontFactory.java
 Sun Aug  2 10:59:48 2026        (r1936797)
+++ 
pdfbox/trunk/pdfbox/src/main/java/org/apache/pdfbox/pdmodel/font/PDFontFactory.java
 Sun Aug  2 15:58:22 2026        (r1936798)
@@ -362,10 +362,12 @@ public final class PDFontFactory
      * Creates a new PDCIDFont instance with the appropriate subclass.
      *
      * @param dictionary descendant font dictionary
+     * @param resourceCache ResourceCache, can be null.
+     * 
      * @return a PDCIDFont instance, based on the SubType entry of the 
dictionary
      * @throws IOException if something goes wrong
      */
-    static PDCIDFont createDescendantFont(COSDictionary dictionary)
+    static PDCIDFont createDescendantFont(COSDictionary dictionary, 
ResourceCache resourceCache)
             throws IOException
     {
         COSName type = dictionary.getCOSName(COSName.TYPE, COSName.FONT);
@@ -376,11 +378,11 @@ public final class PDFontFactory
         COSName subType = dictionary.getCOSName(COSName.SUBTYPE);
         if (COSName.CID_FONT_TYPE0.equals(subType))
         {
-            return new PDCIDFontType0(dictionary);
+            return new PDCIDFontType0(dictionary, resourceCache);
         }
         if (COSName.CID_FONT_TYPE2.equals(subType))
         {
-            return new PDCIDFontType2(dictionary);
+            return new PDCIDFontType2(dictionary, resourceCache);
         }
         throw new IOException("Invalid font type: " + type);
     }

Modified: 
pdfbox/trunk/pdfbox/src/main/java/org/apache/pdfbox/pdmodel/font/PDType0Font.java
==============================================================================
--- 
pdfbox/trunk/pdfbox/src/main/java/org/apache/pdfbox/pdmodel/font/PDType0Font.java
   Sun Aug  2 10:59:48 2026        (r1936797)
+++ 
pdfbox/trunk/pdfbox/src/main/java/org/apache/pdfbox/pdmodel/font/PDType0Font.java
   Sun Aug  2 15:58:22 2026        (r1936798)
@@ -108,7 +108,7 @@ public class PDType0Font extends PDFont
         if (cachedCIDFont == null)
         {
             cachedCIDFont = PDFontFactory
-                    .createDescendantFont((COSDictionary) 
descendantFontDictBase);
+                    .createDescendantFont((COSDictionary) 
descendantFontDictBase, resourceCache);
             if (resourceCache != null && descendantFontBaseObject instanceof 
COSObject)
             {
                 resourceCache.put((COSObject) descendantFontBaseObject, 
cachedCIDFont);

Reply via email to