7#include "core/fpdfapi/page/cpdf_occontext.h"
9#include "core/fpdfapi/page/cpdf_pageobject.h"
10#include "core/fpdfapi/parser/cpdf_array.h"
11#include "core/fpdfapi/parser/cpdf_dictionary.h"
12#include "core/fpdfapi/parser/cpdf_document.h"
13#include "third_party/base/check.h"
17bool HasIntent(
const CPDF_Dictionary* pDict,
18 ByteStringView csElement,
19 ByteStringView csDef) {
22 return csElement == csDef;
25 if (
const CPDF_Array* pArray = pIntent->AsArray()) {
26 for (size_t i = 0; i < pArray->size(); i++) {
27 bsIntent = pArray->GetByteStringAt(i);
28 if (bsIntent
== "All" || bsIntent == csElement)
33 bsIntent = pIntent->GetString();
34 return bsIntent
== "All" || bsIntent == csElement;
38 const CPDF_Dictionary* pOCGDict) {
40 RetainPtr<
const CPDF_Dictionary> pOCProperties =
41 pDoc->GetRoot()->GetDictFor(
"OCProperties");
45 RetainPtr<
const CPDF_Array> pOCGs = pOCProperties->GetArrayFor(
"OCGs");
49 if (!pOCGs->Contains(pOCGDict))
52 RetainPtr<
const CPDF_Dictionary> pConfig = pOCProperties->GetDictFor(
"D");
53 RetainPtr<
const CPDF_Array> pConfigArray =
54 pOCProperties->GetArrayFor(
"Configs");
58 for (size_t i = 0; i < pConfigArray->size(); i++) {
59 RetainPtr<
const CPDF_Dictionary> pFind = pConfigArray->GetDictAt(i);
60 if (pFind && HasIntent(pFind.Get(),
"View",
""))
66ByteString GetUsageTypeString(CPDF_OCContext::
UsageType eType) {
88 : m_pDocument(pDoc), m_eUsageType(eUsageType) {
94bool CPDF_OCContext::LoadOCGStateFromConfig(
95 const ByteString& csConfig,
96 const CPDF_Dictionary* pOCGDict)
const {
97 RetainPtr<
const CPDF_Dictionary> pConfig = GetConfig(m_pDocument, pOCGDict);
101 bool bState = pConfig->GetByteStringFor(
"BaseState",
"ON") !=
"OFF";
102 RetainPtr<
const CPDF_Array> pArray = pConfig->GetArrayFor(
"ON");
103 if (pArray && pArray->Contains(pOCGDict))
106 pArray = pConfig->GetArrayFor(
"OFF");
107 if (pArray && pArray->Contains(pOCGDict))
110 pArray = pConfig->GetArrayFor(
"AS");
114 ByteString csFind = csConfig
+ "State";
115 for (size_t i = 0; i < pArray->size(); i++) {
116 RetainPtr<
const CPDF_Dictionary> pUsage = pArray->GetDictAt(i);
120 if (pUsage->GetByteStringFor(
"Event",
"View") != csConfig)
123 RetainPtr<
const CPDF_Array> pOCGs = pUsage->GetArrayFor(
"OCGs");
127 if (!pOCGs->Contains(pOCGDict))
130 RetainPtr<
const CPDF_Dictionary> pState = pUsage->GetDictFor(csConfig);
134 bState = pState->GetByteStringFor(csFind) !=
"OFF";
139bool CPDF_OCContext::LoadOCGState(
const CPDF_Dictionary* pOCGDict)
const {
140 if (!HasIntent(pOCGDict,
"View",
"View"))
143 ByteString csState = GetUsageTypeString(m_eUsageType);
144 RetainPtr<
const CPDF_Dictionary> pUsage = pOCGDict->GetDictFor(
"Usage");
146 RetainPtr<
const CPDF_Dictionary> pState = pUsage->GetDictFor(csState);
148 ByteString csFind = csState
+ "State";
149 if (pState->KeyExist(csFind))
150 return pState->GetByteStringFor(csFind) !=
"OFF";
152 if (csState
!= "View") {
153 pState = pUsage->GetDictFor(
"View");
154 if (pState && pState->KeyExist(
"ViewState"))
155 return pState->GetByteStringFor(
"ViewState") !=
"OFF";
158 return LoadOCGStateFromConfig(csState, pOCGDict);
161bool CPDF_OCContext::GetOCGVisible(
const CPDF_Dictionary* pOCGDict)
const {
165 const auto it = m_OGCStateCache.find(pOCGDict);
166 if (it != m_OGCStateCache.end())
169 bool bState = LoadOCGState(pOCGDict);
170 m_OGCStateCache[pdfium::WrapRetain(pOCGDict)] = bState;
176 for (size_t i = 0; i < pMarks->CountItems(); ++i) {
177 const CPDF_ContentMarkItem* item = pMarks->GetItem(i);
187bool CPDF_OCContext::GetOCGVE(
const CPDF_Array* pExpression,
int nLevel)
const {
188 if (nLevel > 32 || !pExpression)
191 ByteString csOperator = pExpression->GetByteStringAt(0);
192 if (csOperator
== "Not") {
196 if (
const CPDF_Dictionary* pDict = pOCGObj->AsDictionary())
197 return !GetOCGVisible(pDict);
198 if (
const CPDF_Array* pArray = pOCGObj->AsArray())
199 return !GetOCGVE(pArray, nLevel + 1);
203 if (csOperator
!= "Or" && csOperator
!= "And")
207 for (size_t i = 1; i < pExpression->size(); i++) {
213 if (
const CPDF_Dictionary* pDict = pOCGObj->AsDictionary())
214 bItem = GetOCGVisible(pDict);
215 else if (
const CPDF_Array* pArray = pOCGObj->AsArray())
216 bItem = GetOCGVE(pArray, nLevel + 1);
221 if (csOperator
== "Or") {
222 bValue = bValue || bItem;
224 bValue = bValue && bItem;
231bool CPDF_OCContext::LoadOCMDState(
const CPDF_Dictionary* pOCMDDict)
const {
232 RetainPtr<
const CPDF_Array> pVE = pOCMDDict->GetArrayFor(
"VE");
234 return GetOCGVE(pVE.Get(), 0);
242 if (
const CPDF_Dictionary* pDict = pOCGObj->AsDictionary())
243 return GetOCGVisible(pDict);
245 const CPDF_Array* pArray = pOCGObj->AsArray();
249 bool bState = (csP
== "AllOn" || csP
== "AllOff");
252 bool bValidEntrySeen =
false;
253 for (size_t i = 0; i < pArray->size(); i++) {
255 RetainPtr<
const CPDF_Dictionary> pItemDict = pArray->GetDictAt(i);
259 bValidEntrySeen =
true;
260 bItem = GetOCGVisible(pItemDict.Get());
262 if ((csP
== "AnyOn" && bItem) || (csP
== "AnyOff" && !bItem))
264 if ((csP
== "AllOn" && !bItem) || (csP
== "AllOff" && bItem))
268 return !bValidEntrySeen || bState;
272 const CPDF_Dictionary* pOCGDict)
const {
278 return GetOCGVisible(pOCGDict);
279 return LoadOCMDState(pOCGDict);
const ByteString & GetName() const
ParamType GetParamType() const
RetainPtr< const CPDF_Dictionary > GetParam() const
ByteString GetByteStringFor(const ByteString &key, const ByteString &default_str) const
bool CheckPageObjectVisible(const CPDF_PageObject *pObj) const
bool CheckOCGDictVisible(const CPDF_Dictionary *pOCGDict) const
~CPDF_OCContext() override
const CPDF_ContentMarks * GetContentMarks() const
bool operator==(const char *ptr) const
ByteString & operator=(const char *str)
bool operator!=(const char *ptr) const
ByteString operator+(const ByteString &str1, const char *str2)