• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright 2020 Google Inc.
3  *
4  * Use of this source code is governed by a BSD-style license that can be
5  * found in the LICENSE file.
6  */
7 #include "tests/Test.h"
8 
9 #ifdef SK_SUPPORT_PDF
10 
11 #include "include/core/SkCanvas.h"
12 #include "include/core/SkFont.h"
13 #include "include/core/SkStream.h"
14 #include "include/docs/SkPDFDocument.h"
15 
16 using PDFTag = SkPDF::StructureElementNode;
17 
18 // Test building a tagged PDF containing a table.
19 // Add this to args.gn to output the PDF to a file:
20 //   extra_cflags = [ "-DSK_PDF_TEST_TAGS_OUTPUT_PATH=\"/tmp/table.pdf\"" ]
DEF_TEST(SkPDF_tagged_table,r)21 DEF_TEST(SkPDF_tagged_table, r) {
22     REQUIRE_PDF_DOCUMENT(SkPDF_tagged, r);
23 #ifdef SK_PDF_TEST_TAGS_OUTPUT_PATH
24     SkFILEWStream outputStream(SK_PDF_TEST_TAGS_OUTPUT_PATH);
25 #else
26     SkDynamicMemoryWStream outputStream;
27 #endif
28 
29     SkSize pageSize = SkSize::Make(612, 792);  // U.S. Letter
30 
31     SkPDF::Metadata metadata;
32     metadata.fTitle = "Example Tagged Table PDF";
33     metadata.fCreator = "Skia";
34     SkTime::DateTime now;
35     SkTime::GetDateTime(&now);
36     metadata.fCreation = now;
37     metadata.fModified = now;
38 
39     constexpr int kRowCount = 5;
40     constexpr int kColCount = 4;
41     const char* cellData[kRowCount * kColCount] = {
42         "Car",                  "Engine",   "City MPG", "Highway MPG",
43         "Mitsubishi Mirage ES", "Gas",      "28",       "47",
44         "Toyota Prius Three",   "Hybrid",   "43",       "59",
45         "Nissan Leaf SL",       "Electric", "N/A",      nullptr,
46         "Tesla Model 3",        nullptr,    "N/A",      nullptr
47     };
48 
49     // The document tag.
50     auto root = std::make_unique<PDFTag>();
51     root->fNodeId = 1;
52     root->fTypeString = "Document";
53     root->fLang = "en-US";
54 
55     // Heading.
56     auto h1 = std::make_unique<PDFTag>();
57     h1->fNodeId = 2;
58     h1->fTypeString = "H1";
59     h1->fAlt = "Tagged PDF Table Alt Text";
60     root->fChildVector.push_back(std::move(h1));
61 
62     // Table.
63     auto table = std::make_unique<PDFTag>();
64     table->fNodeId = 3;
65     table->fTypeString = "Table";
66     auto& rows = table->fChildVector;
67     table->fAttributes.appendFloatArray("Layout", "BBox", {72, 72, 360, 360});
68 
69     for (int rowIndex = 0; rowIndex < kRowCount; rowIndex++) {
70         auto row = std::make_unique<PDFTag>();
71         row->fNodeId = 4 + rowIndex;
72         row->fTypeString = "TR";
73         auto& cells = row->fChildVector;
74         for (int colIndex = 0; colIndex < kColCount; colIndex++) {
75             auto cell = std::make_unique<PDFTag>();
76             int cellIndex = rowIndex * kColCount + colIndex;
77             cell->fNodeId = 10 + cellIndex;
78             if (!cellData[cellIndex]) {
79                 cell->fTypeString = "NonStruct";
80             } else if (rowIndex == 0 || colIndex == 0) {
81                 cell->fTypeString = "TH";
82             } else {
83                 cell->fTypeString = "TD";
84             }
85             cell->fChildCount = 0;
86 
87             if (cellIndex == 13) {
88                 cell->fAttributes.appendInt("Table", "RowSpan", 2);
89             } else if (cellIndex == 14 || cellIndex == 18) {
90                 cell->fAttributes.appendInt("Table", "ColSpan", 2);
91             } else if (rowIndex == 0 || colIndex == 0) {
92                 cell->fAttributes.appendString(
93                     "Table", "Scope", rowIndex == 0 ? "Column" : "Row");
94             }
95             cells.push_back(std::move(cell));
96         }
97         rows.push_back(std::move(row));
98     }
99     root->fChildVector.push_back(std::move(table));
100 
101     metadata.fStructureElementTreeRoot = root.get();
102     sk_sp<SkDocument> document = SkPDF::MakeDocument(
103         &outputStream, metadata);
104 
105     SkPaint paint;
106     paint.setColor(SK_ColorBLACK);
107 
108     SkCanvas* canvas =
109             document->beginPage(pageSize.width(),
110                                 pageSize.height());
111     SkPDF::SetNodeId(canvas, 2);
112     SkFont font(nullptr, 36);
113     canvas->drawString("Tagged PDF Table", 72, 72, font, paint);
114 
115     font.setSize(14);
116     for (int rowIndex = 0; rowIndex < kRowCount; rowIndex++) {
117         for (int colIndex = 0; colIndex < kColCount; colIndex++) {
118             int cellIndex = rowIndex * kColCount + colIndex;
119             const char* str = cellData[cellIndex];
120             if (!str)
121                 continue;
122 
123             int x = 72 + colIndex * 108 + (colIndex > 0 ? 72 : 0);
124             int y = 144 + rowIndex * 48;
125 
126             SkPDF::SetNodeId(canvas, 10 + cellIndex);
127             canvas->drawString(str, x, y, font, paint);
128         }
129     }
130 
131     document->endPage();
132     document->close();
133     outputStream.flush();
134 }
135 
136 #endif
137