Flutter Engine
The Flutter Engine
PDFTaggedTableTest.cpp
Go to the documentation of this file.
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
14#include "include/core/SkFont.h"
17#include "include/core/SkSize.h"
22#include "src/pdf/SkPDFUtils.h"
24
25#include <memory>
26#include <utility>
27#include <vector>
28
29using PDFTag = SkPDF::StructureElementNode;
30
31// Test building a tagged PDF containing a table.
32// Add this to args.gn to output the PDF to a file:
33// extra_cflags = [ "-DSK_PDF_TEST_TAGS_OUTPUT_PATH=\"/tmp/table.pdf\"" ]
34DEF_TEST(SkPDF_tagged_table, r) {
35 REQUIRE_PDF_DOCUMENT(SkPDF_tagged, r);
36#ifdef SK_PDF_TEST_TAGS_OUTPUT_PATH
37 SkFILEWStream outputStream(SK_PDF_TEST_TAGS_OUTPUT_PATH);
38#else
39 SkDynamicMemoryWStream outputStream;
40#endif
41
42 SkSize pageSize = SkSize::Make(612, 792); // U.S. Letter
43
44 SkPDF::Metadata metadata;
45 metadata.fTitle = "Example Tagged Table PDF";
46 metadata.fCreator = "Skia";
49 metadata.fCreation = now;
50 metadata.fModified = now;
51
52 constexpr int kRowCount = 5;
53 constexpr int kColCount = 4;
54 const char* cellData[kRowCount * kColCount] = {
55 "Car", "Engine", "City MPG", "Highway MPG",
56 "Mitsubishi Mirage ES", "Gas", "28", "47",
57 "Toyota Prius Three", "Hybrid", "43", "59",
58 "Nissan Leaf SL", "Electric", "N/A", nullptr,
59 "Tesla Model 3", nullptr, "N/A", nullptr
60 };
61
62 // The document tag.
63 auto root = std::make_unique<PDFTag>();
64 root->fNodeId = 1;
65 root->fTypeString = "Document";
66 root->fLang = "en-US";
67
68 // Heading.
69 auto h1 = std::make_unique<PDFTag>();
70 h1->fNodeId = 2;
71 h1->fTypeString = "H1";
72 h1->fAlt = "Tagged PDF Table Alt Text";
73 root->fChildVector.push_back(std::move(h1));
74
75 // Table.
76 auto table = std::make_unique<PDFTag>();
77 table->fNodeId = 3;
78 table->fTypeString = "Table";
79 auto& rows = table->fChildVector;
80 table->fAttributes.appendFloatArray("Layout", "BBox", {72, 72, 360, 360});
81
82 for (int rowIndex = 0; rowIndex < kRowCount; rowIndex++) {
83 auto row = std::make_unique<PDFTag>();
84 row->fNodeId = 4 + rowIndex;
85 row->fTypeString = "TR";
86 auto& cells = row->fChildVector;
87 for (int colIndex = 0; colIndex < kColCount; colIndex++) {
88 auto cell = std::make_unique<PDFTag>();
89 int cellIndex = rowIndex * kColCount + colIndex;
90 cell->fNodeId = 10 + cellIndex;
91 if (!cellData[cellIndex]) {
92 cell->fTypeString = "NonStruct";
93 } else if (rowIndex == 0 || colIndex == 0) {
94 cell->fTypeString = "TH";
95 } else {
96 cell->fTypeString = "TD";
97 std::vector<int> headerIds;
98 headerIds.push_back(10 + rowIndex * kColCount); // Row header
99 headerIds.push_back(10 + colIndex); // Col header.
100 cell->fAttributes.appendNodeIdArray(
101 "Table", "Headers", headerIds);
102 }
103
104 if (cellIndex == 13) {
105 cell->fAttributes.appendInt("Table", "RowSpan", 2);
106 } else if (cellIndex == 14 || cellIndex == 18) {
107 cell->fAttributes.appendInt("Table", "ColSpan", 2);
108 } else if (rowIndex == 0 || colIndex == 0) {
109 cell->fAttributes.appendName(
110 "Table", "Scope", rowIndex == 0 ? "Column" : "Row");
111 }
112 cells.push_back(std::move(cell));
113 }
114 rows.push_back(std::move(row));
115 }
116 root->fChildVector.push_back(std::move(table));
117
118 metadata.fStructureElementTreeRoot = root.get();
120 &outputStream, metadata);
121
123 paint.setColor(SK_ColorBLACK);
124
125 SkCanvas* canvas =
126 document->beginPage(pageSize.width(),
127 pageSize.height());
128 SkPDF::SetNodeId(canvas, 2);
130 canvas->drawString("Tagged PDF Table", 72, 72, font, paint);
131
132 font.setSize(14);
133 for (int rowIndex = 0; rowIndex < kRowCount; rowIndex++) {
134 for (int colIndex = 0; colIndex < kColCount; colIndex++) {
135 int cellIndex = rowIndex * kColCount + colIndex;
136 const char* str = cellData[cellIndex];
137 if (!str)
138 continue;
139
140 int x = 72 + colIndex * 108 + (colIndex > 0 ? 72 : 0);
141 int y = 144 + rowIndex * 48;
142
143 SkPDF::SetNodeId(canvas, 10 + cellIndex);
144 canvas->drawString(str, x, y, font, paint);
145 }
146 }
147
148 document->endPage();
149 document->close();
150 outputStream.flush();
151}
152
153#endif
constexpr SkColor SK_ColorBLACK
Definition: SkColor.h:103
#define DEF_TEST(name, reporter)
Definition: Test.h:312
#define REQUIRE_PDF_DOCUMENT(TEST_NAME, REPORTER)
Definition: Test.h:485
SI F table(const skcms_Curve *curve, F v)
void drawString(const char str[], SkScalar x, SkScalar y, const SkFont &font, const SkPaint &paint)
Definition: SkCanvas.h:1803
Definition: SkFont.h:35
virtual void flush()
Definition: SkStream.cpp:77
const Paint & paint
Definition: color_source.cc:38
static constexpr int kRowCount
static constexpr int kColCount
double y
double x
void GetDateTime(SkPDF::DateTime *)
Definition: SkPDFUtils.cpp:431
SK_API sk_sp< SkDocument > MakeDocument(SkWStream *stream, const Metadata &metadata)
SK_API void SetNodeId(SkCanvas *dst, int nodeID)
sk_sp< SkTypeface > DefaultTypeface()
font
Font Metadata and Metrics.
string root
Definition: scale_cpu.py:20
StructureElementNode * fStructureElementTreeRoot
DateTime fCreation
DateTime fModified
Definition: SkSize.h:52
static constexpr SkSize Make(SkScalar w, SkScalar h)
Definition: SkSize.h:56
SkScalar width() const
Definition: SkSize.h:76
SkScalar height() const
Definition: SkSize.h:77