Author: tilman
Date: Wed Oct 9 11:05:09 2024
New Revision: 1921203
URL: http://svn.apache.org/viewvc?rev=1921203&view=rev
Log:
PDFBOX-5884: support OCG visibility expressions
Modified:
pdfbox/trunk/pdfbox/src/main/java/org/apache/pdfbox/rendering/PageDrawer.java
Modified:
pdfbox/trunk/pdfbox/src/main/java/org/apache/pdfbox/rendering/PageDrawer.java
URL:
http://svn.apache.org/viewvc/pdfbox/trunk/pdfbox/src/main/java/org/apache/pdfbox/rendering/PageDrawer.java?rev=1921203&r1=1921202&r2=1921203&view=diff
==============================================================================
---
pdfbox/trunk/pdfbox/src/main/java/org/apache/pdfbox/rendering/PageDrawer.java
(original)
+++
pdfbox/trunk/pdfbox/src/main/java/org/apache/pdfbox/rendering/PageDrawer.java
Wed Oct 9 11:05:09 2024
@@ -2099,10 +2099,10 @@ public class PageDrawer extends PDFGraph
private boolean isHiddenOCMD(PDOptionalContentMembershipDictionary ocmd)
{
- if (ocmd.getCOSObject().getCOSArray(COSName.VE) != null)
+ COSArray veArray = ocmd.getCOSObject().getCOSArray(COSName.VE);
+ if (veArray != null && !veArray.isEmpty())
{
- // support seems to be optional, and is approximated by /P and
/OCGS
- LOG.info("/VE entry ignored in Optional Content Membership
Dictionary");
+ return isHiddenVisibilityExpression(veArray);
}
List<PDPropertyList> oCGs = ocmd.getOCGs();
if (oCGs.isEmpty())
@@ -2136,6 +2136,109 @@ public class PageDrawer extends PDFGraph
return visibles.stream().noneMatch(v -> v);
}
+ private boolean isHiddenVisibilityExpression(COSArray veArray)
+ {
+ if (veArray.isEmpty())
+ {
+ return false;
+ }
+ String op = veArray.getName(0);
+ if (op == null)
+ {
+ return false;
+ }
+ switch (op)
+ {
+ case "And":
+ return isHiddenAndVisibilityExpression(veArray);
+ case "Or":
+ return isHiddenOrVisibilityExpression(veArray);
+ case "Not":
+ return isHiddenNotVisibilityExpression(veArray);
+ default:
+ return false;
+ }
+ }
+
+ private boolean isHiddenAndVisibilityExpression(COSArray veArray)
+ {
+ // hidden if at least one isn't visible
+ for (int i = 1; i < veArray.size(); ++i)
+ {
+ COSBase base = veArray.getObject(i);
+ if (base instanceof COSArray)
+ {
+ // Another VE
+ boolean isHidden = isHiddenVisibilityExpression((COSArray)
base);
+ if (isHidden)
+ {
+ return true;
+ }
+ }
+ else if (base instanceof COSDictionary)
+ {
+ // Another OCG
+ PDPropertyList prop =
PDOptionalContentGroup.create((COSDictionary) base);
+ boolean isHidden = isHiddenOCG(prop);
+ if (isHidden)
+ {
+ return true;
+ }
+ }
+ }
+ return false;
+ }
+
+ private boolean isHiddenOrVisibilityExpression(COSArray veArray)
+ {
+ // hidden only if all are hidden
+ for (int i = 1; i < veArray.size(); ++i)
+ {
+ COSBase base = veArray.getObject(i);
+ if (base instanceof COSArray)
+ {
+ // Another VE
+ boolean isHidden = isHiddenVisibilityExpression((COSArray)
base);
+ if (!isHidden)
+ {
+ return false;
+ }
+ }
+ else if (base instanceof COSDictionary)
+ {
+ // Another OCG
+ PDPropertyList prop =
PDOptionalContentGroup.create((COSDictionary) base);
+ boolean isHidden = isHiddenOCG(prop);
+ if (!isHidden)
+ {
+ return false;
+ }
+ }
+ }
+ return true;
+ }
+
+ private boolean isHiddenNotVisibilityExpression(COSArray veArray)
+ {
+ if (veArray.size() != 2)
+ {
+ return false;
+ }
+ COSBase base = veArray.getObject(1);
+ if (base instanceof COSArray)
+ {
+ // Another VE
+ return !isHiddenVisibilityExpression((COSArray) base);
+ }
+ else if (base instanceof COSDictionary)
+ {
+ // Another OCG
+ PDPropertyList prop =
PDOptionalContentGroup.create((COSDictionary) base);
+ return !isHiddenOCG(prop);
+ }
+ return false;
+ }
+
private LookupTable getInvLookupTable()
{
if (invTable == null)