Author: lehmi
Date: Fri Jan 31 07:24:46 2025
New Revision: 1923474
URL: http://svn.apache.org/viewvc?rev=1923474&view=rev
Log:
PDFBOX-5943: add a method to remove all page resources from the cache
Modified:
pdfbox/trunk/pdfbox/src/main/java/org/apache/pdfbox/pdmodel/PDPage.java
Modified:
pdfbox/trunk/pdfbox/src/main/java/org/apache/pdfbox/pdmodel/PDPage.java
URL:
http://svn.apache.org/viewvc/pdfbox/trunk/pdfbox/src/main/java/org/apache/pdfbox/pdmodel/PDPage.java?rev=1923474&r1=1923473&r2=1923474&view=diff
==============================================================================
--- pdfbox/trunk/pdfbox/src/main/java/org/apache/pdfbox/pdmodel/PDPage.java
(original)
+++ pdfbox/trunk/pdfbox/src/main/java/org/apache/pdfbox/pdmodel/PDPage.java Fri
Jan 31 07:24:46 2025
@@ -20,6 +20,7 @@ import java.io.ByteArrayInputStream;
import java.io.IOException;
import java.io.InputStream;
import java.util.ArrayList;
+import java.util.Collections;
import java.util.Iterator;
import java.util.List;
import java.util.stream.Collectors;
@@ -46,6 +47,8 @@ import org.apache.pdfbox.pdmodel.common.
import org.apache.pdfbox.pdmodel.common.PDMetadata;
import org.apache.pdfbox.pdmodel.common.PDRectangle;
import org.apache.pdfbox.pdmodel.common.PDStream;
+import org.apache.pdfbox.pdmodel.graphics.PDXObject;
+import org.apache.pdfbox.pdmodel.graphics.form.PDFormXObject;
import org.apache.pdfbox.pdmodel.interactive.action.PDPageAdditionalActions;
import org.apache.pdfbox.pdmodel.interactive.annotation.AnnotationFilter;
import org.apache.pdfbox.pdmodel.interactive.annotation.PDAnnotation;
@@ -115,6 +118,64 @@ public class PDPage implements COSObject
}
/**
+ * Remove all page resources from the cache to avoid relying on the
implementation of the Cache. Does make sense
+ * after processing a page.
+ */
+ public void removePageResourceFromCache()
+ {
+ if (resourceCache == null)
+ {
+ return;
+ }
+ // limit purge operation to page resources, don't remove inherited
resources
+ removeResources(page.getCOSDictionary(COSName.RESOURCES));
+ }
+
+ private void removeResources(COSDictionary resources)
+ {
+ if (resources == null)
+ {
+ return;
+ }
+ getIndirectResourceObjects(resources, COSName.COLORSPACE)
+ .forEach(resourceCache::removeColorSpace);
+ getIndirectResourceObjects(resources, COSName.EXT_G_STATE)
+ .forEach(resourceCache::removeExtState);
+ getIndirectResourceObjects(resources, COSName.FONT)
+ .forEach(resourceCache::removeFont);
+ getIndirectResourceObjects(resources, COSName.PATTERN)
+ .forEach(resourceCache::removePattern);
+ getIndirectResourceObjects(resources, COSName.PROPERTIES)
+ .forEach(resourceCache::removeProperties);
+ getIndirectResourceObjects(resources, COSName.SHADING)
+ .forEach(resourceCache::removeShading);
+ for (COSObject cosObject : getIndirectResourceObjects(resources,
COSName.XOBJECT))
+ {
+ PDXObject removedXObject = resourceCache.removeXObject(cosObject);
+ // clean up the resources of the XFormObject
+ if (removedXObject instanceof PDFormXObject)
+ {
+ COSStream cosStream = removedXObject.getCOSObject();
+ removeResources(cosStream.getCOSDictionary(COSName.RESOURCES));
+ }
+ }
+ }
+
+ private List<COSObject> getIndirectResourceObjects(COSDictionary
pageResources, COSName kind)
+ {
+ COSDictionary resourcesDictionary =
pageResources.getCOSDictionary(kind);
+ if (resourcesDictionary == null)
+ {
+ return Collections.emptyList();
+ }
+ return resourcesDictionary.getValues().stream() //
+ .filter(f -> f instanceof COSObject) //
+ .map(f -> (COSObject) f) //
+ .filter(COSObject::isDereferenced) //
+ .collect(Collectors.toList());
+ }
+
+ /**
* Convert this standard java object to a COS object.
*
* @return The cos object that matches this Java object.