OLD | NEW |
1 // Copyright 2014 PDFium Authors. All rights reserved. | 1 // Copyright 2014 PDFium Authors. All rights reserved. |
2 // Use of this source code is governed by a BSD-style license that can be | 2 // Use of this source code is governed by a BSD-style license that can be |
3 // found in the LICENSE file. | 3 // found in the LICENSE file. |
4 | 4 |
5 // Original code copyright 2014 Foxit Software Inc. http://www.foxitsoftware.com | 5 // Original code copyright 2014 Foxit Software Inc. http://www.foxitsoftware.com |
6 | 6 |
7 #include "../../include/fpdfdoc/fpdf_doc.h" | 7 #include "../../include/fpdfdoc/fpdf_doc.h" |
8 static int32_t FPDFDOC_OCG_FindGroup(const CPDF_Object *pObject, const CPDF_Dict
ionary *pGroupDict) | 8 static int32_t FPDFDOC_OCG_FindGroup(const CPDF_Object* pObject, |
9 { | 9 const CPDF_Dictionary* pGroupDict) { |
10 if (pObject == NULL || pGroupDict == NULL) { | 10 if (pObject == NULL || pGroupDict == NULL) { |
11 return -1; | 11 return -1; |
12 } | 12 } |
13 int32_t iType = pObject->GetType(); | 13 int32_t iType = pObject->GetType(); |
14 if (iType == PDFOBJ_ARRAY) { | 14 if (iType == PDFOBJ_ARRAY) { |
15 FX_DWORD dwCount = ((CPDF_Array*)pObject)->GetCount(); | 15 FX_DWORD dwCount = ((CPDF_Array*)pObject)->GetCount(); |
16 for (FX_DWORD i = 0; i < dwCount; i++) { | 16 for (FX_DWORD i = 0; i < dwCount; i++) { |
17 if (((CPDF_Array*)pObject)->GetDict(i) == pGroupDict) { | 17 if (((CPDF_Array*)pObject)->GetDict(i) == pGroupDict) { |
18 return i; | 18 return i; |
19 } | 19 } |
| 20 } |
| 21 return -1; |
| 22 } |
| 23 if (pObject->GetDict() == pGroupDict) { |
| 24 return 0; |
| 25 } |
| 26 return -1; |
| 27 } |
| 28 static FX_BOOL FPDFDOC_OCG_HasIntent( |
| 29 const CPDF_Dictionary* pDict, |
| 30 const CFX_ByteStringC& csElement, |
| 31 const CFX_ByteStringC& csDef = FX_BSTRC("")) { |
| 32 FXSYS_assert(pDict != NULL); |
| 33 CPDF_Object* pIntent = pDict->GetElementValue(FX_BSTRC("Intent")); |
| 34 if (pIntent == NULL) { |
| 35 return csElement == csDef; |
| 36 } |
| 37 CFX_ByteString bsIntent; |
| 38 if (pIntent->GetType() == PDFOBJ_ARRAY) { |
| 39 FX_DWORD dwCount = ((CPDF_Array*)pIntent)->GetCount(); |
| 40 for (FX_DWORD i = 0; i < dwCount; i++) { |
| 41 bsIntent = ((CPDF_Array*)pIntent)->GetString(i); |
| 42 if (bsIntent == FX_BSTRC("All") || bsIntent == csElement) { |
| 43 return TRUE; |
| 44 } |
| 45 } |
| 46 return FALSE; |
| 47 } |
| 48 bsIntent = pIntent->GetString(); |
| 49 return bsIntent == FX_BSTRC("All") || bsIntent == csElement; |
| 50 } |
| 51 static CPDF_Dictionary* FPDFDOC_OCG_GetConfig(CPDF_Document* pDoc, |
| 52 const CPDF_Dictionary* pOCGDict, |
| 53 const CFX_ByteStringC& bsState) { |
| 54 FXSYS_assert(pDoc && pOCGDict); |
| 55 CPDF_Dictionary* pOCProperties = |
| 56 pDoc->GetRoot()->GetDict(FX_BSTRC("OCProperties")); |
| 57 if (!pOCProperties) { |
| 58 return NULL; |
| 59 } |
| 60 CPDF_Array* pOCGs = pOCProperties->GetArray(FX_BSTRC("OCGs")); |
| 61 if (!pOCGs) { |
| 62 return NULL; |
| 63 } |
| 64 if (FPDFDOC_OCG_FindGroup(pOCGs, pOCGDict) < 0) { |
| 65 return NULL; |
| 66 } |
| 67 CPDF_Dictionary* pConfig = pOCProperties->GetDict(FX_BSTRC("D")); |
| 68 CPDF_Array* pConfigs = pOCProperties->GetArray(FX_BSTRC("Configs")); |
| 69 if (pConfigs) { |
| 70 CPDF_Dictionary* pFind; |
| 71 int32_t iCount = pConfigs->GetCount(); |
| 72 for (int32_t i = 0; i < iCount; i++) { |
| 73 pFind = pConfigs->GetDict(i); |
| 74 if (!pFind) { |
| 75 continue; |
| 76 } |
| 77 if (!FPDFDOC_OCG_HasIntent(pFind, FX_BSTRC("View"), FX_BSTRC("View"))) { |
| 78 continue; |
| 79 } |
| 80 pConfig = pFind; |
| 81 break; |
| 82 } |
| 83 } |
| 84 return pConfig; |
| 85 } |
| 86 static CFX_ByteString FPDFDOC_OCG_GetUsageTypeString( |
| 87 CPDF_OCContext::UsageType eType) { |
| 88 CFX_ByteString csState = FX_BSTRC("View"); |
| 89 if (eType == CPDF_OCContext::Design) { |
| 90 csState = FX_BSTRC("Design"); |
| 91 } else if (eType == CPDF_OCContext::Print) { |
| 92 csState = FX_BSTRC("Print"); |
| 93 } else if (eType == CPDF_OCContext::Export) { |
| 94 csState = FX_BSTRC("Export"); |
| 95 } |
| 96 return csState; |
| 97 } |
| 98 CPDF_OCContext::CPDF_OCContext(CPDF_Document* pDoc, UsageType eUsageType) { |
| 99 FXSYS_assert(pDoc != NULL); |
| 100 m_pDocument = pDoc; |
| 101 m_eUsageType = eUsageType; |
| 102 } |
| 103 CPDF_OCContext::~CPDF_OCContext() { |
| 104 m_OCGStates.clear(); |
| 105 } |
| 106 FX_BOOL CPDF_OCContext::LoadOCGStateFromConfig(const CFX_ByteStringC& csConfig, |
| 107 const CPDF_Dictionary* pOCGDict, |
| 108 FX_BOOL& bValidConfig) const { |
| 109 CPDF_Dictionary* pConfig = |
| 110 FPDFDOC_OCG_GetConfig(m_pDocument, pOCGDict, csConfig); |
| 111 if (!pConfig) { |
| 112 return TRUE; |
| 113 } |
| 114 bValidConfig = TRUE; |
| 115 FX_BOOL bState = pConfig->GetString(FX_BSTRC("BaseState"), FX_BSTRC("ON")) != |
| 116 FX_BSTRC("OFF"); |
| 117 CPDF_Array* pArray = pConfig->GetArray(FX_BSTRC("ON")); |
| 118 if (pArray) { |
| 119 if (FPDFDOC_OCG_FindGroup(pArray, pOCGDict) >= 0) { |
| 120 bState = TRUE; |
| 121 } |
| 122 } |
| 123 pArray = pConfig->GetArray(FX_BSTRC("OFF")); |
| 124 if (pArray) { |
| 125 if (FPDFDOC_OCG_FindGroup(pArray, pOCGDict) >= 0) { |
| 126 bState = FALSE; |
| 127 } |
| 128 } |
| 129 pArray = pConfig->GetArray(FX_BSTRC("AS")); |
| 130 if (pArray) { |
| 131 CFX_ByteString csFind = csConfig + FX_BSTRC("State"); |
| 132 int32_t iCount = pArray->GetCount(); |
| 133 for (int32_t i = 0; i < iCount; i++) { |
| 134 CPDF_Dictionary* pUsage = pArray->GetDict(i); |
| 135 if (!pUsage) { |
| 136 continue; |
| 137 } |
| 138 if (pUsage->GetString(FX_BSTRC("Event"), FX_BSTRC("View")) != csConfig) { |
| 139 continue; |
| 140 } |
| 141 CPDF_Array* pOCGs = pUsage->GetArray(FX_BSTRC("OCGs")); |
| 142 if (!pOCGs) { |
| 143 continue; |
| 144 } |
| 145 if (FPDFDOC_OCG_FindGroup(pOCGs, pOCGDict) < 0) { |
| 146 continue; |
| 147 } |
| 148 CPDF_Dictionary* pState = pUsage->GetDict(csConfig); |
| 149 if (!pState) { |
| 150 continue; |
| 151 } |
| 152 bState = pState->GetString(csFind) != FX_BSTRC("OFF"); |
| 153 } |
| 154 } |
| 155 return bState; |
| 156 } |
| 157 FX_BOOL CPDF_OCContext::LoadOCGState(const CPDF_Dictionary* pOCGDict) const { |
| 158 if (!FPDFDOC_OCG_HasIntent(pOCGDict, FX_BSTRC("View"), FX_BSTRC("View"))) { |
| 159 return TRUE; |
| 160 } |
| 161 CFX_ByteString csState = FPDFDOC_OCG_GetUsageTypeString(m_eUsageType); |
| 162 CPDF_Dictionary* pUsage = pOCGDict->GetDict(FX_BSTRC("Usage")); |
| 163 if (pUsage) { |
| 164 CPDF_Dictionary* pState = pUsage->GetDict(csState); |
| 165 if (pState) { |
| 166 CFX_ByteString csFind = csState + FX_BSTRC("State"); |
| 167 if (pState->KeyExist(csFind)) { |
| 168 return pState->GetString(csFind) != FX_BSTRC("OFF"); |
| 169 } |
| 170 } |
| 171 if (csState != FX_BSTRC("View")) { |
| 172 pState = pUsage->GetDict(FX_BSTRC("View")); |
| 173 if (pState && pState->KeyExist(FX_BSTRC("ViewState"))) { |
| 174 return pState->GetString(FX_BSTRC("ViewState")) != FX_BSTRC("OFF"); |
| 175 } |
| 176 } |
| 177 } |
| 178 FX_BOOL bDefValid = FALSE; |
| 179 return LoadOCGStateFromConfig(csState, pOCGDict, bDefValid); |
| 180 } |
| 181 |
| 182 FX_BOOL CPDF_OCContext::GetOCGVisible(const CPDF_Dictionary* pOCGDict) { |
| 183 if (!pOCGDict) |
| 184 return FALSE; |
| 185 |
| 186 const auto it = m_OCGStates.find(pOCGDict); |
| 187 if (it != m_OCGStates.end()) |
| 188 return it->second; |
| 189 |
| 190 FX_BOOL bState = LoadOCGState(pOCGDict); |
| 191 m_OCGStates[pOCGDict] = bState; |
| 192 return bState; |
| 193 } |
| 194 |
| 195 FX_BOOL CPDF_OCContext::GetOCGVE(CPDF_Array* pExpression, |
| 196 FX_BOOL bFromConfig, |
| 197 int nLevel) { |
| 198 if (nLevel > 32) { |
| 199 return FALSE; |
| 200 } |
| 201 if (pExpression == NULL) { |
| 202 return FALSE; |
| 203 } |
| 204 int32_t iCount = pExpression->GetCount(); |
| 205 CPDF_Object* pOCGObj; |
| 206 CFX_ByteString csOperator = pExpression->GetString(0); |
| 207 if (csOperator == FX_BSTRC("Not")) { |
| 208 pOCGObj = pExpression->GetElementValue(1); |
| 209 if (pOCGObj == NULL) { |
| 210 return FALSE; |
| 211 } |
| 212 if (pOCGObj->GetType() == PDFOBJ_DICTIONARY) { |
| 213 return !(bFromConfig ? LoadOCGState((CPDF_Dictionary*)pOCGObj) |
| 214 : GetOCGVisible((CPDF_Dictionary*)pOCGObj)); |
| 215 } |
| 216 if (pOCGObj->GetType() == PDFOBJ_ARRAY) { |
| 217 return !GetOCGVE((CPDF_Array*)pOCGObj, bFromConfig, nLevel + 1); |
| 218 } |
| 219 return FALSE; |
| 220 } |
| 221 if (csOperator == FX_BSTRC("Or") || csOperator == FX_BSTRC("And")) { |
| 222 FX_BOOL bValue = FALSE; |
| 223 for (int32_t i = 1; i < iCount; i++) { |
| 224 pOCGObj = pExpression->GetElementValue(1); |
| 225 if (pOCGObj == NULL) { |
| 226 continue; |
| 227 } |
| 228 FX_BOOL bItem = FALSE; |
| 229 if (pOCGObj->GetType() == PDFOBJ_DICTIONARY) { |
| 230 bItem = bFromConfig ? LoadOCGState((CPDF_Dictionary*)pOCGObj) |
| 231 : GetOCGVisible((CPDF_Dictionary*)pOCGObj); |
| 232 } else if (pOCGObj->GetType() == PDFOBJ_ARRAY) { |
| 233 bItem = GetOCGVE((CPDF_Array*)pOCGObj, bFromConfig, nLevel + 1); |
| 234 } |
| 235 if (i == 1) { |
| 236 bValue = bItem; |
| 237 } else { |
| 238 if (csOperator == FX_BSTRC("Or")) { |
| 239 bValue = bValue || bItem; |
| 240 } else { |
| 241 bValue = bValue && bItem; |
20 } | 242 } |
21 return -1; | 243 } |
22 } | 244 } |
23 if (pObject->GetDict() == pGroupDict) { | 245 return bValue; |
24 return 0; | 246 } |
25 } | 247 return FALSE; |
26 return -1; | 248 } |
27 } | 249 FX_BOOL CPDF_OCContext::LoadOCMDState(const CPDF_Dictionary* pOCMDDict, |
28 static FX_BOOL FPDFDOC_OCG_HasIntent(const CPDF_Dictionary *pDict, const CFX_Byt
eStringC& csElement, const CFX_ByteStringC& csDef = FX_BSTRC("")) | 250 FX_BOOL bFromConfig) { |
29 { | 251 FXSYS_assert(pOCMDDict != NULL); |
30 FXSYS_assert(pDict != NULL); | 252 CPDF_Array* pVE = pOCMDDict->GetArray(FX_BSTRC("VE")); |
31 CPDF_Object *pIntent = pDict->GetElementValue(FX_BSTRC("Intent")); | 253 if (pVE != NULL) { |
32 if (pIntent == NULL) { | 254 return GetOCGVE(pVE, bFromConfig); |
33 return csElement == csDef; | 255 } |
34 } | 256 CFX_ByteString csP = pOCMDDict->GetString(FX_BSTRC("P"), FX_BSTRC("AnyOn")); |
35 CFX_ByteString bsIntent; | 257 CPDF_Object* pOCGObj = pOCMDDict->GetElementValue(FX_BSTRC("OCGs")); |
36 if (pIntent->GetType() == PDFOBJ_ARRAY) { | 258 if (pOCGObj == NULL) { |
37 FX_DWORD dwCount = ((CPDF_Array*)pIntent)->GetCount(); | 259 return TRUE; |
38 for (FX_DWORD i = 0; i < dwCount; i++) { | 260 } |
39 bsIntent = ((CPDF_Array*)pIntent)->GetString(i); | 261 if (pOCGObj->GetType() == PDFOBJ_DICTIONARY) { |
40 if (bsIntent == FX_BSTRC("All") || bsIntent == csElement) { | 262 return bFromConfig ? LoadOCGState((CPDF_Dictionary*)pOCGObj) |
41 return TRUE; | 263 : GetOCGVisible((CPDF_Dictionary*)pOCGObj); |
42 } | 264 } |
43 } | 265 if (pOCGObj->GetType() != PDFOBJ_ARRAY) { |
44 return FALSE; | 266 return TRUE; |
45 } | 267 } |
46 bsIntent = pIntent->GetString(); | 268 FX_BOOL bState = FALSE; |
47 return bsIntent == FX_BSTRC("All") || bsIntent == csElement; | 269 if (csP == FX_BSTRC("AllOn") || csP == FX_BSTRC("AllOff")) { |
48 } | 270 bState = TRUE; |
49 static CPDF_Dictionary* FPDFDOC_OCG_GetConfig(CPDF_Document *pDoc, const CPDF_Di
ctionary *pOCGDict, const CFX_ByteStringC& bsState) | 271 } |
50 { | 272 int32_t iCount = ((CPDF_Array*)pOCGObj)->GetCount(); |
51 FXSYS_assert(pDoc && pOCGDict); | 273 for (int32_t i = 0; i < iCount; i++) { |
52 CPDF_Dictionary *pOCProperties = pDoc->GetRoot()->GetDict(FX_BSTRC("OCProper
ties")); | 274 FX_BOOL bItem = TRUE; |
53 if (!pOCProperties) { | 275 CPDF_Dictionary* pItemDict = ((CPDF_Array*)pOCGObj)->GetDict(i); |
54 return NULL; | 276 if (pItemDict) { |
55 } | 277 bItem = bFromConfig ? LoadOCGState(pItemDict) : GetOCGVisible(pItemDict); |
56 CPDF_Array *pOCGs = pOCProperties->GetArray(FX_BSTRC("OCGs")); | 278 } |
57 if (!pOCGs) { | 279 if (csP == FX_BSTRC("AnyOn") && bItem) { |
58 return NULL; | 280 return TRUE; |
59 } | 281 } |
60 if (FPDFDOC_OCG_FindGroup(pOCGs, pOCGDict) < 0) { | 282 if (csP == FX_BSTRC("AnyOff") && !bItem) { |
61 return NULL; | 283 return TRUE; |
62 } | 284 } |
63 CPDF_Dictionary *pConfig = pOCProperties->GetDict(FX_BSTRC("D")); | 285 if (csP == FX_BSTRC("AllOn") && !bItem) { |
64 CPDF_Array *pConfigs = pOCProperties->GetArray(FX_BSTRC("Configs")); | 286 return FALSE; |
65 if (pConfigs) { | 287 } |
66 CPDF_Dictionary *pFind; | 288 if (csP == FX_BSTRC("AllOff") && bItem) { |
67 int32_t iCount = pConfigs->GetCount(); | 289 return FALSE; |
68 for (int32_t i = 0; i < iCount; i ++) { | 290 } |
69 pFind = pConfigs->GetDict(i); | 291 } |
70 if (!pFind) { | 292 return bState; |
71 continue; | 293 } |
72 } | 294 FX_BOOL CPDF_OCContext::CheckOCGVisible(const CPDF_Dictionary* pOCGDict) { |
73 if (!FPDFDOC_OCG_HasIntent(pFind, FX_BSTRC("View"), FX_BSTRC("View")
)) { | 295 if (!pOCGDict) { |
74 continue; | 296 return TRUE; |
75 } | 297 } |
76 pConfig = pFind; | 298 CFX_ByteString csType = |
77 break; | 299 pOCGDict->GetString(FX_BSTRC("Type"), FX_BSTRC("OCG")); |
78 } | 300 if (csType == FX_BSTRC("OCG")) { |
79 } | 301 return GetOCGVisible(pOCGDict); |
80 return pConfig; | 302 } |
81 } | 303 return LoadOCMDState(pOCGDict, FALSE); |
82 static CFX_ByteString FPDFDOC_OCG_GetUsageTypeString(CPDF_OCContext::UsageType e
Type) | 304 } |
83 { | 305 void CPDF_OCContext::ResetOCContext() { |
84 CFX_ByteString csState = FX_BSTRC("View"); | 306 m_OCGStates.clear(); |
85 if (eType == CPDF_OCContext::Design) { | 307 } |
86 csState = FX_BSTRC("Design"); | |
87 } else if (eType == CPDF_OCContext::Print) { | |
88 csState = FX_BSTRC("Print"); | |
89 } else if (eType == CPDF_OCContext::Export) { | |
90 csState = FX_BSTRC("Export"); | |
91 } | |
92 return csState; | |
93 } | |
94 CPDF_OCContext::CPDF_OCContext(CPDF_Document *pDoc, UsageType eUsageType) | |
95 { | |
96 FXSYS_assert(pDoc != NULL); | |
97 m_pDocument = pDoc; | |
98 m_eUsageType = eUsageType; | |
99 } | |
100 CPDF_OCContext::~CPDF_OCContext() | |
101 { | |
102 m_OCGStates.clear(); | |
103 } | |
104 FX_BOOL CPDF_OCContext::LoadOCGStateFromConfig(const CFX_ByteStringC& csConfig,
const CPDF_Dictionary *pOCGDict, FX_BOOL &bValidConfig) const | |
105 { | |
106 CPDF_Dictionary *pConfig = FPDFDOC_OCG_GetConfig(m_pDocument, pOCGDict, csCo
nfig); | |
107 if (!pConfig) { | |
108 return TRUE; | |
109 } | |
110 bValidConfig = TRUE; | |
111 FX_BOOL bState = pConfig->GetString(FX_BSTRC("BaseState"), FX_BSTRC("ON")) !
= FX_BSTRC("OFF"); | |
112 CPDF_Array *pArray = pConfig->GetArray(FX_BSTRC("ON")); | |
113 if (pArray) { | |
114 if (FPDFDOC_OCG_FindGroup(pArray, pOCGDict) >= 0) { | |
115 bState = TRUE; | |
116 } | |
117 } | |
118 pArray = pConfig->GetArray(FX_BSTRC("OFF")); | |
119 if (pArray) { | |
120 if (FPDFDOC_OCG_FindGroup(pArray, pOCGDict) >= 0) { | |
121 bState = FALSE; | |
122 } | |
123 } | |
124 pArray = pConfig->GetArray(FX_BSTRC("AS")); | |
125 if (pArray) { | |
126 CFX_ByteString csFind = csConfig + FX_BSTRC("State"); | |
127 int32_t iCount = pArray->GetCount(); | |
128 for (int32_t i = 0; i < iCount; i ++) { | |
129 CPDF_Dictionary *pUsage = pArray->GetDict(i); | |
130 if (!pUsage) { | |
131 continue; | |
132 } | |
133 if (pUsage->GetString(FX_BSTRC("Event"), FX_BSTRC("View")) != csConf
ig) { | |
134 continue; | |
135 } | |
136 CPDF_Array *pOCGs = pUsage->GetArray(FX_BSTRC("OCGs")); | |
137 if (!pOCGs) { | |
138 continue; | |
139 } | |
140 if (FPDFDOC_OCG_FindGroup(pOCGs, pOCGDict) < 0) { | |
141 continue; | |
142 } | |
143 CPDF_Dictionary *pState = pUsage->GetDict(csConfig); | |
144 if (!pState) { | |
145 continue; | |
146 } | |
147 bState = pState->GetString(csFind) != FX_BSTRC("OFF"); | |
148 } | |
149 } | |
150 return bState; | |
151 } | |
152 FX_BOOL CPDF_OCContext::LoadOCGState(const CPDF_Dictionary *pOCGDict) const | |
153 { | |
154 if (!FPDFDOC_OCG_HasIntent(pOCGDict, FX_BSTRC("View"), FX_BSTRC("View"))) { | |
155 return TRUE; | |
156 } | |
157 CFX_ByteString csState = FPDFDOC_OCG_GetUsageTypeString(m_eUsageType); | |
158 CPDF_Dictionary *pUsage = pOCGDict->GetDict(FX_BSTRC("Usage")); | |
159 if (pUsage) { | |
160 CPDF_Dictionary *pState = pUsage->GetDict(csState); | |
161 if (pState) { | |
162 CFX_ByteString csFind = csState + FX_BSTRC("State"); | |
163 if (pState->KeyExist(csFind)) { | |
164 return pState->GetString(csFind) != FX_BSTRC("OFF"); | |
165 } | |
166 } | |
167 if (csState != FX_BSTRC("View")) { | |
168 pState = pUsage->GetDict(FX_BSTRC("View")); | |
169 if (pState && pState->KeyExist(FX_BSTRC("ViewState"))) { | |
170 return pState->GetString(FX_BSTRC("ViewState")) != FX_BSTRC("OFF
"); | |
171 } | |
172 } | |
173 } | |
174 FX_BOOL bDefValid = FALSE; | |
175 return LoadOCGStateFromConfig(csState, pOCGDict, bDefValid); | |
176 } | |
177 | |
178 FX_BOOL CPDF_OCContext::GetOCGVisible(const CPDF_Dictionary* pOCGDict) | |
179 { | |
180 if (!pOCGDict) | |
181 return FALSE; | |
182 | |
183 const auto it = m_OCGStates.find(pOCGDict); | |
184 if (it != m_OCGStates.end()) | |
185 return it->second; | |
186 | |
187 FX_BOOL bState = LoadOCGState(pOCGDict); | |
188 m_OCGStates[pOCGDict] = bState; | |
189 return bState; | |
190 } | |
191 | |
192 FX_BOOL CPDF_OCContext::GetOCGVE(CPDF_Array *pExpression, FX_BOOL bFromConfig, i
nt nLevel) | |
193 { | |
194 if (nLevel > 32) { | |
195 return FALSE; | |
196 } | |
197 if (pExpression == NULL) { | |
198 return FALSE; | |
199 } | |
200 int32_t iCount = pExpression->GetCount(); | |
201 CPDF_Object *pOCGObj; | |
202 CFX_ByteString csOperator = pExpression->GetString(0); | |
203 if (csOperator == FX_BSTRC("Not")) { | |
204 pOCGObj = pExpression->GetElementValue(1); | |
205 if (pOCGObj == NULL) { | |
206 return FALSE; | |
207 } | |
208 if (pOCGObj->GetType() == PDFOBJ_DICTIONARY) { | |
209 return !(bFromConfig ? LoadOCGState((CPDF_Dictionary*)pOCGObj) : Get
OCGVisible((CPDF_Dictionary*)pOCGObj)); | |
210 } | |
211 if (pOCGObj->GetType() == PDFOBJ_ARRAY) { | |
212 return !GetOCGVE((CPDF_Array*)pOCGObj, bFromConfig, nLevel + 1); | |
213 } | |
214 return FALSE; | |
215 } | |
216 if (csOperator == FX_BSTRC("Or") || csOperator == FX_BSTRC("And")) { | |
217 FX_BOOL bValue = FALSE; | |
218 for (int32_t i = 1; i < iCount; i ++) { | |
219 pOCGObj = pExpression->GetElementValue(1); | |
220 if (pOCGObj == NULL) { | |
221 continue; | |
222 } | |
223 FX_BOOL bItem = FALSE; | |
224 if (pOCGObj->GetType() == PDFOBJ_DICTIONARY) { | |
225 bItem = bFromConfig ? LoadOCGState((CPDF_Dictionary*)pOCGObj) :
GetOCGVisible((CPDF_Dictionary*)pOCGObj); | |
226 } else if (pOCGObj->GetType() == PDFOBJ_ARRAY) { | |
227 bItem = GetOCGVE((CPDF_Array*)pOCGObj, bFromConfig, nLevel + 1); | |
228 } | |
229 if (i == 1) { | |
230 bValue = bItem; | |
231 } else { | |
232 if (csOperator == FX_BSTRC("Or")) { | |
233 bValue = bValue || bItem; | |
234 } else { | |
235 bValue = bValue && bItem; | |
236 } | |
237 } | |
238 } | |
239 return bValue; | |
240 } | |
241 return FALSE; | |
242 } | |
243 FX_BOOL CPDF_OCContext::LoadOCMDState(const CPDF_Dictionary *pOCMDDict, FX_BOOL
bFromConfig) | |
244 { | |
245 FXSYS_assert(pOCMDDict != NULL); | |
246 CPDF_Array *pVE = pOCMDDict->GetArray(FX_BSTRC("VE")); | |
247 if (pVE != NULL) { | |
248 return GetOCGVE(pVE, bFromConfig); | |
249 } | |
250 CFX_ByteString csP = pOCMDDict->GetString(FX_BSTRC("P"), FX_BSTRC("AnyOn")); | |
251 CPDF_Object *pOCGObj = pOCMDDict->GetElementValue(FX_BSTRC("OCGs")); | |
252 if (pOCGObj == NULL) { | |
253 return TRUE; | |
254 } | |
255 if (pOCGObj->GetType() == PDFOBJ_DICTIONARY) { | |
256 return bFromConfig ? LoadOCGState((CPDF_Dictionary*)pOCGObj) : GetOCGVis
ible((CPDF_Dictionary*)pOCGObj); | |
257 } | |
258 if (pOCGObj->GetType() != PDFOBJ_ARRAY) { | |
259 return TRUE; | |
260 } | |
261 FX_BOOL bState = FALSE; | |
262 if (csP == FX_BSTRC("AllOn") || csP == FX_BSTRC("AllOff")) { | |
263 bState = TRUE; | |
264 } | |
265 int32_t iCount = ((CPDF_Array*)pOCGObj)->GetCount(); | |
266 for (int32_t i = 0; i < iCount; i ++) { | |
267 FX_BOOL bItem = TRUE; | |
268 CPDF_Dictionary* pItemDict = ((CPDF_Array*)pOCGObj)->GetDict(i); | |
269 if (pItemDict) { | |
270 bItem = bFromConfig ? LoadOCGState(pItemDict) : GetOCGVisible(pItemD
ict); | |
271 } | |
272 if (csP == FX_BSTRC("AnyOn") && bItem) { | |
273 return TRUE; | |
274 } | |
275 if (csP == FX_BSTRC("AnyOff") && !bItem) { | |
276 return TRUE; | |
277 } | |
278 if (csP == FX_BSTRC("AllOn") && !bItem) { | |
279 return FALSE; | |
280 } | |
281 if (csP == FX_BSTRC("AllOff") && bItem) { | |
282 return FALSE; | |
283 } | |
284 } | |
285 return bState; | |
286 } | |
287 FX_BOOL CPDF_OCContext::CheckOCGVisible(const CPDF_Dictionary *pOCGDict) | |
288 { | |
289 if (!pOCGDict) { | |
290 return TRUE; | |
291 } | |
292 CFX_ByteString csType = pOCGDict->GetString(FX_BSTRC("Type"), FX_BSTRC("OCG"
)); | |
293 if (csType == FX_BSTRC("OCG")) { | |
294 return GetOCGVisible(pOCGDict); | |
295 } | |
296 return LoadOCMDState(pOCGDict, FALSE); | |
297 } | |
298 void CPDF_OCContext::ResetOCContext() | |
299 { | |
300 m_OCGStates.clear(); | |
301 } | |
OLD | NEW |