1 // Copyright 2018 The 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 #include "samples/pdfium_test_dump_helper.h"
6 
7 #include <string.h>
8 
9 #include <algorithm>
10 #include <functional>
11 #include <memory>
12 #include <string>
13 #include <utility>
14 
15 #include "public/cpp/fpdf_scopers.h"
16 #include "public/fpdf_transformpage.h"
17 #include "testing/fx_string_testhelpers.h"
18 
19 using GetBoxInfoFunc =
20     std::function<bool(FPDF_PAGE, float*, float*, float*, float*)>;
21 
22 namespace {
23 
ConvertToWString(const unsigned short * buf,unsigned long buf_size)24 std::wstring ConvertToWString(const unsigned short* buf,
25                               unsigned long buf_size) {
26   std::wstring result;
27   result.reserve(buf_size);
28   std::copy(buf, buf + buf_size, std::back_inserter(result));
29   return result;
30 }
31 
DumpBoxInfo(GetBoxInfoFunc func,const char * box_type,FPDF_PAGE page,int page_idx)32 void DumpBoxInfo(GetBoxInfoFunc func,
33                  const char* box_type,
34                  FPDF_PAGE page,
35                  int page_idx) {
36   FS_RECTF rect;
37   bool ret = func(page, &rect.left, &rect.bottom, &rect.right, &rect.top);
38   if (!ret) {
39     printf("Page %d: No %s.\n", page_idx, box_type);
40     return;
41   }
42   printf("Page %d: %s: %0.2f %0.2f %0.2f %0.2f\n", page_idx, box_type,
43          rect.left, rect.bottom, rect.right, rect.top);
44 }
45 
46 }  // namespace
47 
DumpChildStructure(FPDF_STRUCTELEMENT child,int indent)48 void DumpChildStructure(FPDF_STRUCTELEMENT child, int indent) {
49   static const size_t kBufSize = 1024;
50   unsigned short buf[kBufSize];
51   unsigned long len = FPDF_StructElement_GetType(child, buf, kBufSize);
52   printf("%*s%ls", indent * 2, "", ConvertToWString(buf, len).c_str());
53 
54   memset(buf, 0, sizeof(buf));
55   len = FPDF_StructElement_GetTitle(child, buf, kBufSize);
56   if (len > 0)
57     printf(": '%ls'", ConvertToWString(buf, len).c_str());
58 
59   memset(buf, 0, sizeof(buf));
60   len = FPDF_StructElement_GetAltText(child, buf, kBufSize);
61   if (len > 0)
62     printf(" (%ls)", ConvertToWString(buf, len).c_str());
63   printf("\n");
64 
65   for (int i = 0; i < FPDF_StructElement_CountChildren(child); ++i) {
66     FPDF_STRUCTELEMENT sub_child = FPDF_StructElement_GetChildAtIndex(child, i);
67     // If the child is not an Element then this will return null. This can
68     // happen if the element is things like an object reference or a stream.
69     if (!sub_child)
70       continue;
71 
72     DumpChildStructure(sub_child, indent + 1);
73   }
74 }
75 
DumpPageInfo(FPDF_PAGE page,int page_idx)76 void DumpPageInfo(FPDF_PAGE page, int page_idx) {
77   DumpBoxInfo(&FPDFPage_GetMediaBox, "MediaBox", page, page_idx);
78   DumpBoxInfo(&FPDFPage_GetCropBox, "CropBox", page, page_idx);
79   DumpBoxInfo(&FPDFPage_GetBleedBox, "BleedBox", page, page_idx);
80   DumpBoxInfo(&FPDFPage_GetTrimBox, "TrimBox", page, page_idx);
81   DumpBoxInfo(&FPDFPage_GetArtBox, "ArtBox", page, page_idx);
82 }
83 
DumpPageStructure(FPDF_PAGE page,int page_idx)84 void DumpPageStructure(FPDF_PAGE page, int page_idx) {
85   ScopedFPDFStructTree tree(FPDF_StructTree_GetForPage(page));
86   if (!tree) {
87     fprintf(stderr, "Failed to load struct tree for page %d\n", page_idx);
88     return;
89   }
90 
91   printf("Structure Tree for Page %d\n", page_idx);
92   for (int i = 0; i < FPDF_StructTree_CountChildren(tree.get()); ++i) {
93     FPDF_STRUCTELEMENT child = FPDF_StructTree_GetChildAtIndex(tree.get(), i);
94     if (!child) {
95       fprintf(stderr, "Failed to load child %d for page %d\n", i, page_idx);
96       continue;
97     }
98     DumpChildStructure(child, 0);
99   }
100   printf("\n\n");
101 }
102 
DumpMetaData(FPDF_DOCUMENT doc)103 void DumpMetaData(FPDF_DOCUMENT doc) {
104   static constexpr const char* kMetaTags[] = {
105       "Title",   "Author",   "Subject",      "Keywords",
106       "Creator", "Producer", "CreationDate", "ModDate"};
107   for (const char* meta_tag : kMetaTags) {
108     char meta_buffer[4096];
109     unsigned long len =
110         FPDF_GetMetaText(doc, meta_tag, meta_buffer, sizeof(meta_buffer));
111     if (!len)
112       continue;
113 
114     auto* meta_string = reinterpret_cast<unsigned short*>(meta_buffer);
115     printf("%-12s = %ls (%lu bytes)\n", meta_tag,
116            GetPlatformWString(meta_string).c_str(), len);
117   }
118 }
119