7#include "public/fpdf_structtree.h"
8#include "testing/embedder_test.h"
9#include "testing/fx_string_testhelpers.h"
10#include "third_party/abseil-cpp/absl/types/optional.h"
15 ASSERT_TRUE(OpenDocument(
"tagged_alt_text.pdf"));
16 FPDF_PAGE page = LoadPage(0);
20 ScopedFPDFStructTree struct_tree(FPDF_StructTree_GetForPage(page));
21 ASSERT_TRUE(struct_tree);
22 ASSERT_EQ(1, FPDF_StructTree_CountChildren(struct_tree.get()));
24 FPDF_STRUCTELEMENT element =
25 FPDF_StructTree_GetChildAtIndex(struct_tree.get(), -1);
26 EXPECT_FALSE(element);
27 element = FPDF_StructTree_GetChildAtIndex(struct_tree.get(), 1);
28 EXPECT_FALSE(element);
29 element = FPDF_StructTree_GetChildAtIndex(struct_tree.get(), 0);
35 FPDF_STRUCTELEMENT child_element =
37 EXPECT_FALSE(child_element);
39 EXPECT_FALSE(child_element);
41 ASSERT_TRUE(child_element);
46 FPDF_STRUCTELEMENT gchild_element =
48 EXPECT_FALSE(gchild_element);
50 EXPECT_FALSE(gchild_element);
52 ASSERT_TRUE(gchild_element);
56 unsigned short buffer[12];
57 memset(buffer, 0,
sizeof(buffer));
61 for (size_t i = 0; i <
std::size(buffer); ++i)
62 EXPECT_EQ(0U, buffer[i]);
67 EXPECT_EQ(L"Black Image", GetPlatformWString(buffer));
70 FPDF_STRUCTELEMENT ggchild_element =
72 EXPECT_FALSE(ggchild_element);
79 ASSERT_TRUE(OpenDocument(
"tagged_actual_text.pdf"));
80 FPDF_PAGE page = LoadPage(0);
84 ScopedFPDFStructTree struct_tree(FPDF_StructTree_GetForPage(page));
85 ASSERT_TRUE(struct_tree);
86 ASSERT_EQ(1, FPDF_StructTree_CountChildren(struct_tree.get()));
90 FPDF_STRUCTELEMENT element =
91 FPDF_StructTree_GetChildAtIndex(struct_tree.get(), 0);
96 FPDF_STRUCTELEMENT child_element =
98 ASSERT_TRUE(child_element);
102 FPDF_STRUCTELEMENT gchild_element =
104 ASSERT_TRUE(gchild_element);
108 unsigned short buffer[12] = {};
112 for (size_t i = 0; i <
std::size(buffer); ++i)
113 EXPECT_EQ(0U, buffer[i]);
116 EXPECT_EQ(L"Actual Text", GetPlatformWString(buffer));
123 ASSERT_TRUE(OpenDocument(
"tagged_table.pdf"));
124 FPDF_PAGE page = LoadPage(0);
128 ScopedFPDFStructTree struct_tree(FPDF_StructTree_GetForPage(page));
129 ASSERT_TRUE(struct_tree);
130 ASSERT_EQ(1, FPDF_StructTree_CountChildren(struct_tree.get()));
132 FPDF_STRUCTELEMENT document =
133 FPDF_StructTree_GetChildAtIndex(struct_tree.get(), 0);
134 ASSERT_TRUE(document);
136 constexpr int kBufLen = 100;
137 uint16_t buffer[kBufLen] = {0};
139 EXPECT_EQ(
"Document", GetPlatformString(buffer));
146 EXPECT_EQ(
"Table", GetPlatformString(buffer));
158 ASSERT_TRUE(header_cell);
161 EXPECT_EQ(
"TH", GetPlatformString(buffer));
166 EXPECT_EQ(
"Row", GetPlatformString(buffer));
186 ASSERT_TRUE(OpenDocument(
"tagged_table_bad_elem.pdf"));
187 FPDF_PAGE page = LoadPage(0);
191 ScopedFPDFStructTree struct_tree(FPDF_StructTree_GetForPage(page));
192 ASSERT_TRUE(struct_tree);
193 ASSERT_EQ(1, FPDF_StructTree_CountChildren(struct_tree.get()));
195 FPDF_STRUCTELEMENT document =
196 FPDF_StructTree_GetChildAtIndex(struct_tree.get(), 0);
197 ASSERT_TRUE(document);
199 constexpr int kBufLen = 100;
200 uint16_t buffer[kBufLen] = {0};
202 EXPECT_EQ(
"Document", GetPlatformString(buffer));
210 EXPECT_EQ(
"Table", GetPlatformString(buffer));
226 ASSERT_TRUE(OpenDocument(
"tagged_table.pdf"));
227 FPDF_PAGE page = LoadPage(0);
231 ScopedFPDFStructTree struct_tree(FPDF_StructTree_GetForPage(page));
232 ASSERT_TRUE(struct_tree);
233 ASSERT_EQ(1, FPDF_StructTree_CountChildren(struct_tree.get()));
235 FPDF_STRUCTELEMENT document =
236 FPDF_StructTree_GetChildAtIndex(struct_tree.get(), 0);
237 ASSERT_TRUE(document);
239 constexpr int kBufLen = 100;
240 uint16_t buffer[kBufLen] = {0};
242 EXPECT_EQ(
"Document", GetPlatformString(buffer));
252 EXPECT_EQ(
"Table", GetPlatformString(buffer));
256 EXPECT_EQ(
"node12", GetPlatformString(buffer));
271 ASSERT_TRUE(OpenDocument(
"tagged_table.pdf"));
272 FPDF_PAGE page = LoadPage(0);
276 ScopedFPDFStructTree struct_tree(FPDF_StructTree_GetForPage(page));
277 ASSERT_TRUE(struct_tree);
278 ASSERT_EQ(1, FPDF_StructTree_CountChildren(struct_tree.get()));
280 FPDF_STRUCTELEMENT document =
281 FPDF_StructTree_GetChildAtIndex(struct_tree.get(), 0);
282 ASSERT_TRUE(document);
284 constexpr int kBufLen = 100;
285 uint16_t buffer[kBufLen] = {0};
287 EXPECT_EQ(
"Document", GetPlatformString(buffer));
294 EXPECT_EQ(
"en-US", GetPlatformString(buffer));
302 EXPECT_EQ(
"Table", GetPlatformString(buffer));
305 EXPECT_EQ(
"hu", GetPlatformString(buffer));
321 ASSERT_TRUE(OpenDocument(
"marked_content_id.pdf"));
322 FPDF_PAGE page = LoadPage(0);
326 ScopedFPDFStructTree struct_tree(FPDF_StructTree_GetForPage(page));
327 ASSERT_TRUE(struct_tree);
328 ASSERT_EQ(1, FPDF_StructTree_CountChildren(struct_tree.get()));
330 FPDF_STRUCTELEMENT element =
331 FPDF_StructTree_GetChildAtIndex(struct_tree.get(), 0);
339 ASSERT_TRUE(OpenDocument(
"tagged_marked_content.pdf"));
340 FPDF_PAGE page = LoadPage(0);
344 ScopedFPDFStructTree struct_tree(FPDF_StructTree_GetForPage(page));
345 ASSERT_TRUE(struct_tree);
346 ASSERT_EQ(4, FPDF_StructTree_CountChildren(struct_tree.get()));
349 FPDF_STRUCTELEMENT child1 =
350 FPDF_StructTree_GetChildAtIndex(struct_tree.get(), 0);
356 FPDF_STRUCTELEMENT child2 =
357 FPDF_StructTree_GetChildAtIndex(struct_tree.get(), 1);
361 FPDF_STRUCTELEMENT child3 =
362 FPDF_StructTree_GetChildAtIndex(struct_tree.get(), 2);
366 FPDF_STRUCTELEMENT child4 =
367 FPDF_StructTree_GetChildAtIndex(struct_tree.get(), 3);
393 ASSERT_TRUE(OpenDocument(
"tagged_mcr_multipage.pdf"));
396 for (
int page_i : {0, 1}) {
397 FPDF_PAGE page = LoadPage(page_i);
399 ScopedFPDFStructTree struct_tree(FPDF_StructTree_GetForPage(page));
400 ASSERT_TRUE(struct_tree);
401 ASSERT_EQ(1, FPDF_StructTree_CountChildren(struct_tree.get()));
403 FPDF_STRUCTELEMENT struct_doc =
404 FPDF_StructTree_GetChildAtIndex(struct_tree.get(), 0);
405 ASSERT_TRUE(struct_doc);
406 EXPECT_EQ(-1, FPDF_StructElement_GetMarkedContentID(struct_doc));
408 ASSERT_EQ(2, FPDF_StructElement_CountChildren(struct_doc));
409 FPDF_STRUCTELEMENT child1 =
410 FPDF_StructElement_GetChildAtIndex(struct_doc, 0);
411 EXPECT_FALSE(child1);
412 FPDF_STRUCTELEMENT child2 =
413 FPDF_StructElement_GetChildAtIndex(struct_doc, 1);
414 EXPECT_FALSE(child2);
416 EXPECT_EQ(2, FPDF_StructElement_GetMarkedContentIdCount(struct_doc));
421 EXPECT_EQ(0, FPDF_StructElement_GetMarkedContentIdAtIndex(struct_doc, 0));
422 EXPECT_EQ(0, FPDF_StructElement_GetMarkedContentIdAtIndex(struct_doc, 1));
426 EXPECT_EQ(page_i == 0 ? 0 : -1,
427 FPDF_StructElement_GetChildMarkedContentID(struct_doc, 0));
428 EXPECT_EQ(page_i == 1 ? 0 : -1,
429 FPDF_StructElement_GetChildMarkedContentID(struct_doc, 1));
431 EXPECT_EQ(-1, FPDF_StructElement_GetChildMarkedContentID(struct_doc, -1));
432 EXPECT_EQ(-1, FPDF_StructElement_GetChildMarkedContentID(struct_doc, 2));
434 EXPECT_EQ(-1, FPDF_StructElement_GetChildMarkedContentID(
nullptr, 0));
440 ASSERT_TRUE(OpenDocument(
"tagged_alt_text.pdf"));
441 FPDF_PAGE page = LoadPage(0);
445 ScopedFPDFStructTree struct_tree(FPDF_StructTree_GetForPage(page));
446 ASSERT_TRUE(struct_tree);
447 ASSERT_EQ(1, FPDF_StructTree_CountChildren(struct_tree.get()));
449 FPDF_STRUCTELEMENT element =
450 FPDF_StructTree_GetChildAtIndex(struct_tree.get(), 0);
451 ASSERT_TRUE(element);
454 unsigned short buffer[12];
459 memset(buffer, 0,
sizeof(buffer));
463 for (size_t i = 0; i <
std::size(buffer); ++i)
464 EXPECT_EQ(0U, buffer[i]);
467 EXPECT_EQ(L"Document", GetPlatformWString(buffer));
474 ASSERT_TRUE(OpenDocument(
"tagged_table_bad_elem.pdf"));
475 FPDF_PAGE page = LoadPage(0);
479 ScopedFPDFStructTree struct_tree(FPDF_StructTree_GetForPage(page));
480 ASSERT_TRUE(struct_tree);
481 ASSERT_EQ(1, FPDF_StructTree_CountChildren(struct_tree.get()));
483 FPDF_STRUCTELEMENT child =
484 FPDF_StructTree_GetChildAtIndex(struct_tree.get(), 0);
488 unsigned short buffer[28] = {};
497 for (size_t i = 0; i <
std::size(buffer); ++i)
498 EXPECT_EQ(0U, buffer[i]);
502 EXPECT_EQ(L"StructElem", GetPlatformWString(buffer));
506 memset(buffer, 0,
sizeof(buffer));
511 for (size_t i = 0; i <
std::size(buffer); ++i)
512 EXPECT_EQ(0U, buffer[i]);
519 EXPECT_EQ(L"NotStructElem", GetPlatformWString(buffer));
526 ASSERT_TRUE(OpenDocument(
"tagged_alt_text.pdf"));
527 FPDF_PAGE page = LoadPage(0);
531 ScopedFPDFStructTree struct_tree(FPDF_StructTree_GetForPage(page));
532 ASSERT_TRUE(struct_tree);
533 ASSERT_EQ(1, FPDF_StructTree_CountChildren(struct_tree.get()));
535 FPDF_STRUCTELEMENT parent =
536 FPDF_StructTree_GetChildAtIndex(struct_tree.get(), 0);
558 ASSERT_TRUE(OpenDocument(
"tagged_alt_text.pdf"));
559 FPDF_PAGE page = LoadPage(0);
563 ScopedFPDFStructTree struct_tree(FPDF_StructTree_GetForPage(page));
564 ASSERT_TRUE(struct_tree);
565 ASSERT_EQ(1, FPDF_StructTree_CountChildren(struct_tree.get()));
567 FPDF_STRUCTELEMENT element =
568 FPDF_StructTree_GetChildAtIndex(struct_tree.get(), 0);
569 ASSERT_TRUE(element);
572 unsigned short buffer[13];
577 memset(buffer, 0,
sizeof(buffer));
581 for (size_t i = 0; i <
std::size(buffer); ++i)
582 EXPECT_EQ(0U, buffer[i]);
587 EXPECT_EQ(L"TitleText", GetPlatformWString(buffer));
590 FPDF_STRUCTELEMENT child_element =
592 ASSERT_TRUE(element);
596 EXPECT_EQ(L"symbol: 100k", GetPlatformWString(buffer));
603 ASSERT_TRUE(OpenDocument(
"tagged_table.pdf"));
604 FPDF_PAGE page = LoadPage(0);
608 ScopedFPDFStructTree struct_tree(FPDF_StructTree_GetForPage(page));
609 ASSERT_TRUE(struct_tree);
610 ASSERT_EQ(1, FPDF_StructTree_CountChildren(struct_tree.get()));
612 FPDF_STRUCTELEMENT document =
613 FPDF_StructTree_GetChildAtIndex(struct_tree.get(), 0);
614 ASSERT_TRUE(document);
638 FPDF_STRUCTELEMENT_ATTR attr =
645 unsigned long buffer_len_needed = ULONG_MAX;
648 &buffer_len_needed
));
649 EXPECT_EQ(2U, buffer_len_needed);
651 unsigned long out_len = ULONG_MAX;
656 EXPECT_EQ(2U, out_len);
657 for (size_t i = 0; i <
std::size(buffer); ++i)
658 EXPECT_EQ(0, buffer[i]);
661 sizeof(buffer)
, &out_len
));
662 EXPECT_EQ(2U, out_len);
663 EXPECT_STREQ(
"O", buffer);
667 unsigned short str_val[12] = {};
669 attr
, buffer
, str_val
, sizeof(str_val)
, &out_len
));
670 EXPECT_EQ(12U, out_len);
671 EXPECT_EQ(L"Table", GetPlatformWString(str_val));
673 memset(buffer, 0,
sizeof(buffer));
675 sizeof(buffer)
, &out_len
));
676 EXPECT_EQ(8U, out_len);
677 EXPECT_STREQ(
"ColSpan", buffer);
683 EXPECT_FLOAT_EQ(2.0f, num_val);
700 FPDF_STRUCTELEMENT_ATTR attr =
706 char buffer[16] = {};
707 unsigned long out_len = ULONG_MAX;
709 attr
, 0
, buffer
, sizeof(buffer)
, &out_len
));
710 EXPECT_EQ(8U, out_len);
711 EXPECT_STREQ(
"ColProp", buffer);
716 unsigned short str_val[12] = {};
718 attr
, buffer
, str_val
, sizeof(str_val)
, &out_len
));
719 EXPECT_EQ(8U, out_len);
720 EXPECT_EQ(L"Sum", GetPlatformWString(str_val));
722 char blob_val[3] = {};
724 attr
, buffer
, blob_val
, sizeof(blob_val)
, &out_len
));
725 EXPECT_EQ(3U, out_len);
726 EXPECT_EQ(
'S', blob_val[0]);
727 EXPECT_EQ(
'u', blob_val[1]);
728 EXPECT_EQ(
'm', blob_val[2]);
733 char buffer[16] = {};
734 unsigned long out_len = ULONG_MAX;
736 attr
, 1
, buffer
, sizeof(buffer)
, &out_len
));
737 EXPECT_EQ(7U, out_len);
738 EXPECT_STREQ(
"CurUSD", buffer);
750 char buffer[16] = {};
751 unsigned long out_len = ULONG_MAX;
753 attr
, 3
, buffer
, sizeof(buffer)
, &out_len
));
754 EXPECT_EQ(8U, out_len);
755 EXPECT_STREQ(
"RowSpan", buffer);
762 EXPECT_FLOAT_EQ(3, val);
772 ASSERT_TRUE(OpenDocument(
"tagged_nested.pdf"));
773 FPDF_PAGE page = LoadPage(0);
778 ScopedFPDFStructTree struct_tree(FPDF_StructTree_GetForPage(page));
779 ASSERT_TRUE(struct_tree);
785 ASSERT_TRUE(OpenDocument(
"tagged_mcr_objr.pdf"));
786 FPDF_PAGE page = LoadPage(0);
790 ScopedFPDFStructTree struct_tree(FPDF_StructTree_GetForPage(page));
791 ASSERT_TRUE(struct_tree);
792 ASSERT_EQ(1, FPDF_StructTree_CountChildren(struct_tree.get()));
794 FPDF_STRUCTELEMENT object8 =
795 FPDF_StructTree_GetChildAtIndex(struct_tree.get(), 0);
796 ASSERT_TRUE(object8);
797 unsigned short buffer[12];
799 EXPECT_EQ(L"Document", GetPlatformWString(buffer));
804 FPDF_STRUCTELEMENT object10 =
806 ASSERT_TRUE(object10);
809 EXPECT_EQ(L"NonStruct", GetPlatformWString(buffer));
813 FPDF_STRUCTELEMENT object12 =
815 ASSERT_TRUE(object12);
817 EXPECT_EQ(L"P", GetPlatformWString(buffer));
821 FPDF_STRUCTELEMENT object13 =
823 ASSERT_TRUE(object13);
826 EXPECT_EQ(L"NonStruct", GetPlatformWString(buffer));
835 FPDF_STRUCTELEMENT object11 =
837 ASSERT_TRUE(object11);
839 EXPECT_EQ(L"P", GetPlatformWString(buffer));
843 FPDF_STRUCTELEMENT object14 =
845 ASSERT_TRUE(object14);
848 EXPECT_EQ(L"NonStruct", GetPlatformWString(buffer));
854 FPDF_STRUCTELEMENT object15 =
856 ASSERT_TRUE(object15);
859 EXPECT_EQ(L"NonStruct", GetPlatformWString(buffer));
871 ASSERT_TRUE(OpenDocument(
"bug_1768.pdf"));
872 FPDF_PAGE page = LoadPage(0);
876 ScopedFPDFStructTree struct_tree(FPDF_StructTree_GetForPage(page));
877 ASSERT_TRUE(struct_tree);
878 ASSERT_EQ(1, FPDF_StructTree_CountChildren(struct_tree.get()));
883 EXPECT_FALSE(FPDF_StructTree_GetChildAtIndex(struct_tree.get(), 0));
890 ASSERT_TRUE(OpenDocument(
"bug_1296920.pdf"));
891 FPDF_PAGE page = LoadPage(0);
895 ScopedFPDFStructTree struct_tree(FPDF_StructTree_GetForPage(page));
896 ASSERT_TRUE(struct_tree);
897 ASSERT_EQ(1, FPDF_StructTree_CountChildren(struct_tree.get()));
906 ASSERT_TRUE(OpenDocument(
"tagged_table_bad_parent.pdf"));
907 FPDF_PAGE page = LoadPage(0);
912 ScopedFPDFStructTree struct_tree(FPDF_StructTree_GetForPage(page));
913 ASSERT_TRUE(struct_tree);
914 ASSERT_EQ(1, FPDF_StructTree_CountChildren(struct_tree.get()));
FPDF_EXPORT FPDF_STRUCTELEMENT FPDF_CALLCONV FPDF_StructElement_GetParent(FPDF_STRUCTELEMENT struct_element)
FPDF_EXPORT unsigned long FPDF_CALLCONV FPDF_StructElement_GetLang(FPDF_STRUCTELEMENT struct_element, void *buffer, unsigned long buflen)
FPDF_EXPORT int FPDF_CALLCONV FPDF_StructElement_GetAttributeCount(FPDF_STRUCTELEMENT struct_element)
FPDF_EXPORT FPDF_BOOL FPDF_CALLCONV FPDF_StructElement_Attr_GetStringValue(FPDF_STRUCTELEMENT_ATTR struct_attribute, FPDF_BYTESTRING name, void *buffer, unsigned long buflen, unsigned long *out_buflen)
FPDF_EXPORT FPDF_BOOL FPDF_CALLCONV FPDF_StructElement_Attr_GetBooleanValue(FPDF_STRUCTELEMENT_ATTR struct_attribute, FPDF_BYTESTRING name, FPDF_BOOL *out_value)
FPDF_EXPORT int FPDF_CALLCONV FPDF_StructElement_GetMarkedContentID(FPDF_STRUCTELEMENT struct_element)
FPDF_EXPORT unsigned long FPDF_CALLCONV FPDF_StructElement_GetStringAttribute(FPDF_STRUCTELEMENT struct_element, FPDF_BYTESTRING attr_name, void *buffer, unsigned long buflen)
FPDF_EXPORT FPDF_BOOL FPDF_CALLCONV FPDF_StructElement_Attr_GetBlobValue(FPDF_STRUCTELEMENT_ATTR struct_attribute, FPDF_BYTESTRING name, void *buffer, unsigned long buflen, unsigned long *out_buflen)
FPDF_EXPORT FPDF_BOOL FPDF_CALLCONV FPDF_StructElement_Attr_GetName(FPDF_STRUCTELEMENT_ATTR struct_attribute, int index, void *buffer, unsigned long buflen, unsigned long *out_buflen)
FPDF_EXPORT int FPDF_CALLCONV FPDF_StructElement_GetMarkedContentIdAtIndex(FPDF_STRUCTELEMENT struct_element, int index)
FPDF_EXPORT unsigned long FPDF_CALLCONV FPDF_StructElement_GetActualText(FPDF_STRUCTELEMENT struct_element, void *buffer, unsigned long buflen)
FPDF_EXPORT int FPDF_CALLCONV FPDF_StructElement_Attr_GetCount(FPDF_STRUCTELEMENT_ATTR struct_attribute)
FPDF_EXPORT unsigned long FPDF_CALLCONV FPDF_StructElement_GetID(FPDF_STRUCTELEMENT struct_element, void *buffer, unsigned long buflen)
FPDF_EXPORT FPDF_BOOL FPDF_CALLCONV FPDF_StructElement_Attr_GetNumberValue(FPDF_STRUCTELEMENT_ATTR struct_attribute, FPDF_BYTESTRING name, float *out_value)
FPDF_EXPORT FPDF_STRUCTELEMENT FPDF_CALLCONV FPDF_StructElement_GetChildAtIndex(FPDF_STRUCTELEMENT struct_element, int index)
FPDF_EXPORT unsigned long FPDF_CALLCONV FPDF_StructElement_GetObjType(FPDF_STRUCTELEMENT struct_element, void *buffer, unsigned long buflen)
FPDF_EXPORT FPDF_OBJECT_TYPE FPDF_CALLCONV FPDF_StructElement_Attr_GetType(FPDF_STRUCTELEMENT_ATTR struct_attribute, FPDF_BYTESTRING name)
FPDF_EXPORT FPDF_STRUCTELEMENT_ATTR FPDF_CALLCONV FPDF_StructElement_GetAttributeAtIndex(FPDF_STRUCTELEMENT struct_element, int index)
FPDF_EXPORT unsigned long FPDF_CALLCONV FPDF_StructElement_GetType(FPDF_STRUCTELEMENT struct_element, void *buffer, unsigned long buflen)
FPDF_EXPORT unsigned long FPDF_CALLCONV FPDF_StructElement_GetAltText(FPDF_STRUCTELEMENT struct_element, void *buffer, unsigned long buflen)
FPDF_EXPORT int FPDF_CALLCONV FPDF_StructElement_CountChildren(FPDF_STRUCTELEMENT struct_element)
FPDF_EXPORT int FPDF_CALLCONV FPDF_StructElement_GetMarkedContentIdCount(FPDF_STRUCTELEMENT struct_element)
FPDF_EXPORT unsigned long FPDF_CALLCONV FPDF_StructElement_GetTitle(FPDF_STRUCTELEMENT struct_element, void *buffer, unsigned long buflen)
TEST_F(FPDFStructTreeEmbedderTest, GetAltText)
#define FPDF_OBJECT_REFERENCE
#define FPDF_OBJECT_NUMBER
#define FPDF_OBJECT_BOOLEAN
#define FPDF_OBJECT_STRING