From 2150b2627df596f83360f328ce6865c057e44eda Mon Sep 17 00:00:00 2001 From: Kakhnovich Raman Date: Thu, 2 Oct 2025 15:22:59 +0300 Subject: [PATCH 1/2] Add support of the /VE tag in OCMD --- src/main/java/org/verapdf/as/ASAtom.java | 4 ++ .../pd/optionalcontent/PDOCMDDictionary.java | 65 +++++++++++++++++-- 2 files changed, 65 insertions(+), 4 deletions(-) diff --git a/src/main/java/org/verapdf/as/ASAtom.java b/src/main/java/org/verapdf/as/ASAtom.java index 402561b4..ea0d66de 100644 --- a/src/main/java/org/verapdf/as/ASAtom.java +++ b/src/main/java/org/verapdf/as/ASAtom.java @@ -66,6 +66,7 @@ public class ASAtom implements Comparable { public static final ASAtom ALT = new ASAtom("Alt"); public static final ASAtom ALTERNATE = new ASAtom("Alternate"); public static final ASAtom ALTERNATES = new ASAtom("Alternates"); + public static final ASAtom AND = new ASAtom("And"); public static final ASAtom ANNOT = new ASAtom("Annot"); public static final ASAtom ANNOTS = new ASAtom("Annots"); public static final ASAtom ANTI_ALIAS = new ASAtom("AntiAlias"); @@ -402,6 +403,7 @@ public class ASAtom implements Comparable { public static final ASAtom NON_EFONT_NO_WARN = new ASAtom("NonEFontNoWarn"); public static final ASAtom NON_FULL_SCREEN_PAGE_MODE = new ASAtom("NonFullScreenPageMode"); public static final ASAtom NONE = new ASAtom("None"); + public static final ASAtom NOT = new ASAtom("Not"); public static final ASAtom NOTE_TYPE = new ASAtom("NoteType"); public static final ASAtom NORMAL = new ASAtom("Normal"); public static final ASAtom NS = new ASAtom("NS"); @@ -426,6 +428,7 @@ public class ASAtom implements Comparable { public static final ASAtom OPI = new ASAtom("OPI"); public static final ASAtom OPM = new ASAtom("OPM"); public static final ASAtom OPT = new ASAtom("Opt"); + public static final ASAtom OR = new ASAtom("Or"); public static final ASAtom ORDER = new ASAtom("Order"); public static final ASAtom ORDERING = new ASAtom("Ordering"); public static final ASAtom OS = new ASAtom("OS"); @@ -603,6 +606,7 @@ public class ASAtom implements Comparable { public static final ASAtom USE_CMAP = new ASAtom("UseCMap"); // V public static final ASAtom V = new ASAtom("V"); + public static final ASAtom VE = new ASAtom("VE"); public static final ASAtom VERISIGN_PPKVS = new ASAtom("VeriSign.PPKVS"); public static final ASAtom VERSION = new ASAtom("Version"); public static final ASAtom VERTICES = new ASAtom("Vertices"); diff --git a/src/main/java/org/verapdf/pd/optionalcontent/PDOCMDDictionary.java b/src/main/java/org/verapdf/pd/optionalcontent/PDOCMDDictionary.java index d638a243..233b47e4 100644 --- a/src/main/java/org/verapdf/pd/optionalcontent/PDOCMDDictionary.java +++ b/src/main/java/org/verapdf/pd/optionalcontent/PDOCMDDictionary.java @@ -1,10 +1,7 @@ package org.verapdf.pd.optionalcontent; import org.verapdf.as.ASAtom; -import org.verapdf.cos.COSArray; -import org.verapdf.cos.COSBase; -import org.verapdf.cos.COSObjType; -import org.verapdf.cos.COSObject; +import org.verapdf.cos.*; public class PDOCMDDictionary { public static boolean isVisibleOCMDByP(COSBase property, PDOptionalContentProperties optProperties) { @@ -34,4 +31,64 @@ public static boolean isVisibleOCMDByP(COSBase property, PDOptionalContentProper } return ASAtom.ALL_OFF.equals(pValue) || ASAtom.ALL_ON.equals(pValue); } + + public static boolean isVisibleOCMD(COSBase property, PDOptionalContentProperties optProperties) { + COSObject veProperty = property.getKey(ASAtom.VE); + if (veProperty != null && veProperty.getType() == COSObjType.COS_ARRAY) { + COSArray veArray = (COSArray) veProperty.getDirectBase(); + return evaluateVE(veArray, optProperties); + } + + return isVisibleOCMDByP(property, optProperties); + } + + private static boolean evaluateVE(COSArray expr, PDOptionalContentProperties optProperties) { + if (expr.size() == 0) return true; + + COSBase first = expr.at(0).getDirectBase(); + + if (first instanceof COSName) { + ASAtom operator = first.getName(); + + if (ASAtom.OR.equals(operator)) { + for (int i = 1; i < expr.size(); i++) { + if (evaluateOperand(expr.at(i).getDirectBase(), optProperties)) { + return true; + } + } + return false; + } else if (ASAtom.AND.equals(operator)) { + for (int i = 1; i < expr.size(); i++) { + if (!evaluateOperand(expr.at(i).getDirectBase(), optProperties)) { + return false; + } + } + return true; + } else if (ASAtom.NOT.equals(operator)) { + if (expr.size() != 2) return true; + return !evaluateOperand(expr.at(1).getDirectBase(), optProperties); + } + } + + for (COSObject obj : expr) { + if (!evaluateOperand(obj.getDirectBase(), optProperties)) { + return false; + } + } + return true; + } + + + private static boolean evaluateOperand(COSBase operand, PDOptionalContentProperties optProperties) { + if (operand instanceof COSArray) { + return evaluateVE((COSArray) operand, optProperties); + + } else if (operand instanceof COSDictionary) { + COSDictionary dict = (COSDictionary) operand; + String name = dict.getStringKey(ASAtom.NAME); + return optProperties.isVisibleLayer(name); + } + + return true; + } } From 238d17a89c03749e5ff56b5cf8ea72b9d90ca626 Mon Sep 17 00:00:00 2001 From: Kakhnovich Raman Date: Thu, 2 Oct 2025 16:29:11 +0300 Subject: [PATCH 2/2] Update PDOCMDDictionary.java --- .../pd/optionalcontent/PDOCMDDictionary.java | 30 ++++++++++++------- 1 file changed, 19 insertions(+), 11 deletions(-) diff --git a/src/main/java/org/verapdf/pd/optionalcontent/PDOCMDDictionary.java b/src/main/java/org/verapdf/pd/optionalcontent/PDOCMDDictionary.java index 233b47e4..9c708bd5 100644 --- a/src/main/java/org/verapdf/pd/optionalcontent/PDOCMDDictionary.java +++ b/src/main/java/org/verapdf/pd/optionalcontent/PDOCMDDictionary.java @@ -3,7 +3,12 @@ import org.verapdf.as.ASAtom; import org.verapdf.cos.*; +import java.util.logging.Level; +import java.util.logging.Logger; + public class PDOCMDDictionary { + private static final Logger LOGGER = Logger.getLogger(PDOCMDDictionary.class.getCanonicalName()); + public static boolean isVisibleOCMDByP(COSBase property, PDOptionalContentProperties optProperties) { COSObject ocgProperty = property.getKey(ASAtom.OCGS); if (ocgProperty == null || ocgProperty.getType() != COSObjType.COS_ARRAY) { @@ -43,7 +48,9 @@ public static boolean isVisibleOCMD(COSBase property, PDOptionalContentPropertie } private static boolean evaluateVE(COSArray expr, PDOptionalContentProperties optProperties) { - if (expr.size() == 0) return true; + if (expr.size() == 0) { + return true; + } COSBase first = expr.at(0).getDirectBase(); @@ -52,34 +59,35 @@ private static boolean evaluateVE(COSArray expr, PDOptionalContentProperties opt if (ASAtom.OR.equals(operator)) { for (int i = 1; i < expr.size(); i++) { - if (evaluateOperand(expr.at(i).getDirectBase(), optProperties)) { + if (evaluateOperandOfVE(expr.at(i).getDirectBase(), optProperties)) { return true; } } return false; } else if (ASAtom.AND.equals(operator)) { for (int i = 1; i < expr.size(); i++) { - if (!evaluateOperand(expr.at(i).getDirectBase(), optProperties)) { + if (!evaluateOperandOfVE(expr.at(i).getDirectBase(), optProperties)) { return false; } } return true; } else if (ASAtom.NOT.equals(operator)) { - if (expr.size() != 2) return true; - return !evaluateOperand(expr.at(1).getDirectBase(), optProperties); + if (expr.size() != 2) { + LOGGER.log(Level.WARNING, "/Not operator should have only 1 argument in VE array"); + return true; + } + return !evaluateOperandOfVE(expr.at(1).getDirectBase(), optProperties); } + LOGGER.log(Level.WARNING, String.format("First element of VE array has value %s instead of /And, /Or or /Not", operator)); + } else { + LOGGER.log(Level.WARNING, "First element of VE array should have type name"); } - for (COSObject obj : expr) { - if (!evaluateOperand(obj.getDirectBase(), optProperties)) { - return false; - } - } return true; } - private static boolean evaluateOperand(COSBase operand, PDOptionalContentProperties optProperties) { + private static boolean evaluateOperandOfVE(COSBase operand, PDOptionalContentProperties optProperties) { if (operand instanceof COSArray) { return evaluateVE((COSArray) operand, optProperties);