Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(69)

Side by Side Diff: core/fpdfdoc/doc_basic.cpp

Issue 2187073005: Splitting fpdfdoc/doc_* part II. (Closed) Base URL: https://pdfium.googlesource.com/pdfium.git@fpdf_doc_III
Patch Set: Rebase to master Created 4 years, 4 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
« no previous file with comments | « core/fpdfdoc/ctypeset.cpp ('k') | core/fpdfdoc/doc_basic_unittest.cpp » ('j') | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
(Empty)
1 // Copyright 2014 PDFium Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file.
4
5 // Original code copyright 2014 Foxit Software Inc. http://www.foxitsoftware.com
6
7 #include "core/fpdfapi/fpdf_parser/include/cpdf_array.h"
8 #include "core/fpdfapi/fpdf_parser/include/cpdf_document.h"
9 #include "core/fpdfapi/fpdf_parser/include/fpdf_parser_decode.h"
10 #include "core/fpdfdoc/doc_utils.h"
11 #include "core/fpdfdoc/cpdf_pagelabel.h"
12 #include "core/fpdfdoc/include/cpdf_filespec.h"
13 #include "core/fpdfdoc/include/cpdf_nametree.h"
14 #include "core/fpdfdoc/include/ipdf_formnotify.h"
15
16 namespace {
17
18 const int nMaxRecursion = 32;
19 const FX_CHAR* const g_sZoomModes[] = {"XYZ", "Fit", "FitH", "FitV", "FitR",
20 "FitB", "FitBH", "FitBV", nullptr};
21
22 } // namespace
23
24 int CPDF_Dest::GetPageIndex(CPDF_Document* pDoc) {
25 CPDF_Array* pArray = ToArray(m_pObj);
26 if (!pArray)
27 return 0;
28
29 CPDF_Object* pPage = pArray->GetDirectObjectAt(0);
30 if (!pPage)
31 return 0;
32 if (pPage->IsNumber())
33 return pPage->GetInteger();
34 if (!pPage->IsDictionary())
35 return 0;
36 return pDoc->GetPageIndex(pPage->GetObjNum());
37 }
38
39 uint32_t CPDF_Dest::GetPageObjNum() {
40 CPDF_Array* pArray = ToArray(m_pObj);
41 if (!pArray)
42 return 0;
43
44 CPDF_Object* pPage = pArray->GetDirectObjectAt(0);
45 if (!pPage)
46 return 0;
47 if (pPage->IsNumber())
48 return pPage->GetInteger();
49 if (pPage->IsDictionary())
50 return pPage->GetObjNum();
51 return 0;
52 }
53
54 int CPDF_Dest::GetZoomMode() {
55 CPDF_Array* pArray = ToArray(m_pObj);
56 if (!pArray)
57 return 0;
58
59 CPDF_Object* pObj = pArray->GetDirectObjectAt(1);
60 if (!pObj)
61 return 0;
62
63 CFX_ByteString mode = pObj->GetString();
64 for (int i = 0; g_sZoomModes[i]; ++i) {
65 if (mode == g_sZoomModes[i])
66 return i + 1;
67 }
68
69 return 0;
70 }
71
72 FX_FLOAT CPDF_Dest::GetParam(int index) {
73 CPDF_Array* pArray = ToArray(m_pObj);
74 return pArray ? pArray->GetNumberAt(2 + index) : 0;
75 }
76
77 CFX_ByteString CPDF_Dest::GetRemoteName() {
78 return m_pObj ? m_pObj->GetString() : CFX_ByteString();
79 }
80
81 CPDF_NameTree::CPDF_NameTree(CPDF_Document* pDoc,
82 const CFX_ByteString& category)
83 : m_pRoot(nullptr) {
84 CPDF_Dictionary* pRoot = pDoc->GetRoot();
85 if (!pRoot)
86 return;
87
88 CPDF_Dictionary* pNames = pRoot->GetDictBy("Names");
89 if (!pNames)
90 return;
91
92 m_pRoot = pNames->GetDictBy(category);
93 }
94
95 static CPDF_Object* SearchNameNode(CPDF_Dictionary* pNode,
96 const CFX_ByteString& csName,
97 size_t& nIndex,
98 CPDF_Array** ppFind,
99 int nLevel = 0) {
100 if (nLevel > nMaxRecursion) {
101 return nullptr;
102 }
103 CPDF_Array* pLimits = pNode->GetArrayBy("Limits");
104 if (pLimits) {
105 CFX_ByteString csLeft = pLimits->GetStringAt(0);
106 CFX_ByteString csRight = pLimits->GetStringAt(1);
107 if (csLeft.Compare(csRight.AsStringC()) > 0) {
108 CFX_ByteString csTmp = csRight;
109 csRight = csLeft;
110 csLeft = csTmp;
111 }
112 if (csName.Compare(csLeft.AsStringC()) < 0 ||
113 csName.Compare(csRight.AsStringC()) > 0) {
114 return nullptr;
115 }
116 }
117 CPDF_Array* pNames = pNode->GetArrayBy("Names");
118 if (pNames) {
119 size_t dwCount = pNames->GetCount() / 2;
120 for (size_t i = 0; i < dwCount; i++) {
121 CFX_ByteString csValue = pNames->GetStringAt(i * 2);
122 int32_t iCompare = csValue.Compare(csName.AsStringC());
123 if (iCompare <= 0) {
124 if (ppFind) {
125 *ppFind = pNames;
126 }
127 if (iCompare < 0) {
128 continue;
129 }
130 } else {
131 break;
132 }
133 nIndex += i;
134 return pNames->GetDirectObjectAt(i * 2 + 1);
135 }
136 nIndex += dwCount;
137 return nullptr;
138 }
139 CPDF_Array* pKids = pNode->GetArrayBy("Kids");
140 if (!pKids) {
141 return nullptr;
142 }
143 for (size_t i = 0; i < pKids->GetCount(); i++) {
144 CPDF_Dictionary* pKid = pKids->GetDictAt(i);
145 if (!pKid) {
146 continue;
147 }
148 CPDF_Object* pFound =
149 SearchNameNode(pKid, csName, nIndex, ppFind, nLevel + 1);
150 if (pFound) {
151 return pFound;
152 }
153 }
154 return nullptr;
155 }
156
157 static CPDF_Object* SearchNameNode(CPDF_Dictionary* pNode,
158 size_t nIndex,
159 size_t& nCurIndex,
160 CFX_ByteString& csName,
161 CPDF_Array** ppFind,
162 int nLevel = 0) {
163 if (nLevel > nMaxRecursion)
164 return nullptr;
165
166 CPDF_Array* pNames = pNode->GetArrayBy("Names");
167 if (pNames) {
168 size_t nCount = pNames->GetCount() / 2;
169 if (nIndex >= nCurIndex + nCount) {
170 nCurIndex += nCount;
171 return nullptr;
172 }
173 if (ppFind)
174 *ppFind = pNames;
175 csName = pNames->GetStringAt((nIndex - nCurIndex) * 2);
176 return pNames->GetDirectObjectAt((nIndex - nCurIndex) * 2 + 1);
177 }
178 CPDF_Array* pKids = pNode->GetArrayBy("Kids");
179 if (!pKids)
180 return nullptr;
181 for (size_t i = 0; i < pKids->GetCount(); i++) {
182 CPDF_Dictionary* pKid = pKids->GetDictAt(i);
183 if (!pKid)
184 continue;
185 CPDF_Object* pFound =
186 SearchNameNode(pKid, nIndex, nCurIndex, csName, ppFind, nLevel + 1);
187 if (pFound)
188 return pFound;
189 }
190 return nullptr;
191 }
192
193 static size_t CountNames(CPDF_Dictionary* pNode, int nLevel = 0) {
194 if (nLevel > nMaxRecursion) {
195 return 0;
196 }
197 CPDF_Array* pNames = pNode->GetArrayBy("Names");
198 if (pNames) {
199 return pNames->GetCount() / 2;
200 }
201 CPDF_Array* pKids = pNode->GetArrayBy("Kids");
202 if (!pKids) {
203 return 0;
204 }
205 size_t nCount = 0;
206 for (size_t i = 0; i < pKids->GetCount(); i++) {
207 CPDF_Dictionary* pKid = pKids->GetDictAt(i);
208 if (!pKid) {
209 continue;
210 }
211 nCount += CountNames(pKid, nLevel + 1);
212 }
213 return nCount;
214 }
215
216 size_t CPDF_NameTree::GetCount() const {
217 if (!m_pRoot) {
218 return 0;
219 }
220 return ::CountNames(m_pRoot);
221 }
222
223 int CPDF_NameTree::GetIndex(const CFX_ByteString& csName) const {
224 if (!m_pRoot) {
225 return -1;
226 }
227 size_t nIndex = 0;
228 if (!SearchNameNode(m_pRoot, csName, nIndex, nullptr)) {
229 return -1;
230 }
231 return nIndex;
232 }
233
234 CPDF_Object* CPDF_NameTree::LookupValue(int nIndex,
235 CFX_ByteString& csName) const {
236 if (!m_pRoot) {
237 return nullptr;
238 }
239 size_t nCurIndex = 0;
240 return SearchNameNode(m_pRoot, nIndex, nCurIndex, csName, nullptr);
241 }
242
243 CPDF_Object* CPDF_NameTree::LookupValue(const CFX_ByteString& csName) const {
244 if (!m_pRoot) {
245 return nullptr;
246 }
247 size_t nIndex = 0;
248 return SearchNameNode(m_pRoot, csName, nIndex, nullptr);
249 }
250
251 CPDF_Array* CPDF_NameTree::LookupNamedDest(CPDF_Document* pDoc,
252 const CFX_ByteString& sName) {
253 CPDF_Object* pValue = LookupValue(sName);
254 if (!pValue) {
255 CPDF_Dictionary* pDests = pDoc->GetRoot()->GetDictBy("Dests");
256 if (!pDests)
257 return nullptr;
258 pValue = pDests->GetDirectObjectBy(sName);
259 }
260 if (!pValue)
261 return nullptr;
262 if (CPDF_Array* pArray = pValue->AsArray())
263 return pArray;
264 if (CPDF_Dictionary* pDict = pValue->AsDictionary())
265 return pDict->GetArrayBy("D");
266 return nullptr;
267 }
268
269 #if _FXM_PLATFORM_ == _FXM_PLATFORM_APPLE_ || \
270 _FXM_PLATFORM_ == _FXM_PLATFORM_WINDOWS_
271 static CFX_WideString ChangeSlashToPlatform(const FX_WCHAR* str) {
272 CFX_WideString result;
273 while (*str) {
274 if (*str == '/') {
275 #if _FXM_PLATFORM_ == _FXM_PLATFORM_APPLE_
276 result += ':';
277 #else
278 result += '\\';
279 #endif
280 } else {
281 result += *str;
282 }
283 str++;
284 }
285 return result;
286 }
287
288 static CFX_WideString ChangeSlashToPDF(const FX_WCHAR* str) {
289 CFX_WideString result;
290 while (*str) {
291 if (*str == '\\' || *str == ':') {
292 result += '/';
293 } else {
294 result += *str;
295 }
296 str++;
297 }
298 return result;
299 }
300 #endif // _FXM_PLATFORM_APPLE_ || _FXM_PLATFORM_WINDOWS_
301
302 CFX_WideString CPDF_FileSpec::DecodeFileName(const CFX_WideStringC& filepath) {
303 if (filepath.GetLength() <= 1)
304 return CFX_WideString();
305
306 #if _FXM_PLATFORM_ == _FXM_PLATFORM_APPLE_
307 if (filepath.Left(sizeof("/Mac") - 1) == CFX_WideStringC(L"/Mac"))
308 return ChangeSlashToPlatform(filepath.c_str() + 1);
309 return ChangeSlashToPlatform(filepath.c_str());
310 #elif _FXM_PLATFORM_ == _FXM_PLATFORM_WINDOWS_
311 if (filepath.GetAt(0) != '/')
312 return ChangeSlashToPlatform(filepath.c_str());
313 if (filepath.GetAt(1) == '/')
314 return ChangeSlashToPlatform(filepath.c_str() + 1);
315 if (filepath.GetAt(2) == '/') {
316 CFX_WideString result;
317 result += filepath.GetAt(1);
318 result += ':';
319 result += ChangeSlashToPlatform(filepath.c_str() + 2);
320 return result;
321 }
322 CFX_WideString result;
323 result += '\\';
324 result += ChangeSlashToPlatform(filepath.c_str());
325 return result;
326 #else
327 return CFX_WideString(filepath);
328 #endif
329 }
330
331 bool CPDF_FileSpec::GetFileName(CFX_WideString* csFileName) const {
332 if (CPDF_Dictionary* pDict = m_pObj->AsDictionary()) {
333 *csFileName = pDict->GetUnicodeTextBy("UF");
334 if (csFileName->IsEmpty()) {
335 *csFileName =
336 CFX_WideString::FromLocal(pDict->GetStringBy("F").AsStringC());
337 }
338 if (pDict->GetStringBy("FS") == "URL")
339 return true;
340 if (csFileName->IsEmpty()) {
341 if (pDict->KeyExist("DOS")) {
342 *csFileName =
343 CFX_WideString::FromLocal(pDict->GetStringBy("DOS").AsStringC());
344 } else if (pDict->KeyExist("Mac")) {
345 *csFileName =
346 CFX_WideString::FromLocal(pDict->GetStringBy("Mac").AsStringC());
347 } else if (pDict->KeyExist("Unix")) {
348 *csFileName =
349 CFX_WideString::FromLocal(pDict->GetStringBy("Unix").AsStringC());
350 } else {
351 return false;
352 }
353 }
354 } else if (m_pObj->IsString()) {
355 *csFileName = CFX_WideString::FromLocal(m_pObj->GetString().AsStringC());
356 } else {
357 return false;
358 }
359 *csFileName = DecodeFileName(csFileName->AsStringC());
360 return true;
361 }
362
363 CPDF_FileSpec::CPDF_FileSpec() {
364 m_pObj = new CPDF_Dictionary;
365 m_pObj->AsDictionary()->SetAtName("Type", "Filespec");
366 }
367
368 CFX_WideString CPDF_FileSpec::EncodeFileName(const CFX_WideStringC& filepath) {
369 if (filepath.GetLength() <= 1) {
370 return CFX_WideString();
371 }
372 #if _FXM_PLATFORM_ == _FXM_PLATFORM_WINDOWS_
373 if (filepath.GetAt(1) == ':') {
374 CFX_WideString result;
375 result = '/';
376 result += filepath.GetAt(0);
377 if (filepath.GetAt(2) != '\\') {
378 result += '/';
379 }
380 result += ChangeSlashToPDF(filepath.c_str() + 2);
381 return result;
382 }
383 if (filepath.GetAt(0) == '\\' && filepath.GetAt(1) == '\\') {
384 return ChangeSlashToPDF(filepath.c_str() + 1);
385 }
386 if (filepath.GetAt(0) == '\\') {
387 CFX_WideString result;
388 result = '/';
389 result += ChangeSlashToPDF(filepath.c_str());
390 return result;
391 }
392 return ChangeSlashToPDF(filepath.c_str());
393 #elif _FXM_PLATFORM_ == _FXM_PLATFORM_APPLE_
394 if (filepath.Left(sizeof("Mac") - 1) == FX_WSTRC(L"Mac")) {
395 CFX_WideString result;
396 result = '/';
397 result += ChangeSlashToPDF(filepath.c_str());
398 return result;
399 }
400 return ChangeSlashToPDF(filepath.c_str());
401 #else
402 return CFX_WideString(filepath);
403 #endif
404 }
405
406 void CPDF_FileSpec::SetFileName(const CFX_WideStringC& wsFileName) {
407 if (!m_pObj)
408 return;
409
410 CFX_WideString wsStr = EncodeFileName(wsFileName);
411 if (m_pObj->IsString()) {
412 m_pObj->SetString(CFX_ByteString::FromUnicode(wsStr));
413 } else if (CPDF_Dictionary* pDict = m_pObj->AsDictionary()) {
414 pDict->SetAtString("F", CFX_ByteString::FromUnicode(wsStr));
415 pDict->SetAtString("UF", PDF_EncodeText(wsStr));
416 }
417 }
418
419 static CFX_WideString _MakeRoman(int num) {
420 const int arabic[] = {1000, 900, 500, 400, 100, 90, 50, 40, 10, 9, 5, 4, 1};
421 const CFX_WideString roman[] = {L"m", L"cm", L"d", L"cd", L"c",
422 L"xc", L"l", L"xl", L"x", L"ix",
423 L"v", L"iv", L"i"};
424 const int nMaxNum = 1000000;
425 num %= nMaxNum;
426 int i = 0;
427 CFX_WideString wsRomanNumber;
428 while (num > 0) {
429 while (num >= arabic[i]) {
430 num = num - arabic[i];
431 wsRomanNumber += roman[i];
432 }
433 i = i + 1;
434 }
435 return wsRomanNumber;
436 }
437
438 static CFX_WideString _MakeLetters(int num) {
439 if (num == 0) {
440 return CFX_WideString();
441 }
442 CFX_WideString wsLetters;
443 const int nMaxCount = 1000;
444 const int nLetterCount = 26;
445 num -= 1;
446 int count = num / nLetterCount + 1;
447 count %= nMaxCount;
448 FX_WCHAR ch = L'a' + num % nLetterCount;
449 for (int i = 0; i < count; i++) {
450 wsLetters += ch;
451 }
452 return wsLetters;
453 }
454
455 static CFX_WideString _GetLabelNumPortion(int num,
456 const CFX_ByteString& bsStyle) {
457 CFX_WideString wsNumPortion;
458 if (bsStyle.IsEmpty()) {
459 return wsNumPortion;
460 }
461 if (bsStyle == "D") {
462 wsNumPortion.Format(L"%d", num);
463 } else if (bsStyle == "R") {
464 wsNumPortion = _MakeRoman(num);
465 wsNumPortion.MakeUpper();
466 } else if (bsStyle == "r") {
467 wsNumPortion = _MakeRoman(num);
468 } else if (bsStyle == "A") {
469 wsNumPortion = _MakeLetters(num);
470 wsNumPortion.MakeUpper();
471 } else if (bsStyle == "a") {
472 wsNumPortion = _MakeLetters(num);
473 }
474 return wsNumPortion;
475 }
476
477 IPDF_FormNotify::~IPDF_FormNotify() {}
478
479 int IPDF_FormNotify::BeforeValueChange(CPDF_FormField* pField,
480 const CFX_WideString& csValue) {
481 return 0;
482 }
483
484 void IPDF_FormNotify::AfterValueChange(CPDF_FormField* pField) {}
485
486 int IPDF_FormNotify::BeforeSelectionChange(CPDF_FormField* pField,
487 const CFX_WideString& csValue) {
488 return 0;
489 }
490
491 void IPDF_FormNotify::AfterSelectionChange(CPDF_FormField* pField) {}
492
493 void IPDF_FormNotify::AfterCheckedStatusChange(CPDF_FormField* pField) {}
494
495 int IPDF_FormNotify::BeforeFormReset(CPDF_InterForm* pForm) {
496 return 0;
497 }
498
499 void IPDF_FormNotify::AfterFormReset(CPDF_InterForm* pForm) {}
500
501 int IPDF_FormNotify::BeforeFormImportData(CPDF_InterForm* pForm) {
502 return 0;
503 }
504
505 void IPDF_FormNotify::AfterFormImportData(CPDF_InterForm* pForm) {}
506
507 CPDF_PageLabel::CPDF_PageLabel(CPDF_Document* pDocument)
508 : m_pDocument(pDocument) {}
509
510 CFX_WideString CPDF_PageLabel::GetLabel(int nPage) const {
511 CFX_WideString wsLabel;
512 if (!m_pDocument) {
513 return wsLabel;
514 }
515 CPDF_Dictionary* pPDFRoot = m_pDocument->GetRoot();
516 if (!pPDFRoot) {
517 return wsLabel;
518 }
519 CPDF_Dictionary* pLabels = pPDFRoot->GetDictBy("PageLabels");
520 CPDF_NumberTree numberTree(pLabels);
521 CPDF_Object* pValue = nullptr;
522 int n = nPage;
523 while (n >= 0) {
524 pValue = numberTree.LookupValue(n);
525 if (pValue) {
526 break;
527 }
528 n--;
529 }
530 if (pValue) {
531 pValue = pValue->GetDirect();
532 if (CPDF_Dictionary* pLabel = pValue->AsDictionary()) {
533 if (pLabel->KeyExist("P")) {
534 wsLabel += pLabel->GetUnicodeTextBy("P");
535 }
536 CFX_ByteString bsNumberingStyle = pLabel->GetStringBy("S", "");
537 int nLabelNum = nPage - n + pLabel->GetIntegerBy("St", 1);
538 CFX_WideString wsNumPortion =
539 _GetLabelNumPortion(nLabelNum, bsNumberingStyle);
540 wsLabel += wsNumPortion;
541 return wsLabel;
542 }
543 }
544 wsLabel.Format(L"%d", nPage + 1);
545 return wsLabel;
546 }
547
548 int32_t CPDF_PageLabel::GetPageByLabel(const CFX_ByteStringC& bsLabel) const {
549 if (!m_pDocument)
550 return -1;
551
552 CPDF_Dictionary* pPDFRoot = m_pDocument->GetRoot();
553 if (!pPDFRoot)
554 return -1;
555
556 int nPages = m_pDocument->GetPageCount();
557 for (int i = 0; i < nPages; i++) {
558 if (PDF_EncodeText(GetLabel(i)).Compare(bsLabel))
559 return i;
560 }
561
562 int nPage = FXSYS_atoi(CFX_ByteString(bsLabel).c_str()); // NUL terminate.
563 return nPage > 0 && nPage <= nPages ? nPage : -1;
564 }
565
566 int32_t CPDF_PageLabel::GetPageByLabel(const CFX_WideStringC& wsLabel) const {
567 return GetPageByLabel(PDF_EncodeText(wsLabel.c_str()).AsStringC());
568 }
OLDNEW
« no previous file with comments | « core/fpdfdoc/ctypeset.cpp ('k') | core/fpdfdoc/doc_basic_unittest.cpp » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698