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 "include/core/SkTypes.h"
8
9 #ifdef SK_SUPPORT_PDF
10 #include "include/core/SkCanvas.h"
11 #include "include/core/SkColor.h"
12 #include "include/core/SkDocument.h"
13 #include "include/core/SkFont.h"
14 #include "include/core/SkPaint.h"
15 #include "include/core/SkRect.h"
16 #include "include/core/SkRefCnt.h"
17 #include "include/core/SkSize.h"
18 #include "include/core/SkStream.h"
19 #include "include/core/SkString.h"
20 #include "include/core/SkTime.h"
21 #include "include/core/SkTypeface.h"
22 #include "include/docs/SkPDFDocument.h"
23 #include "tests/Test.h"
24
25 #include <memory>
26 #include <utility>
27 #include <vector>
28
29 using PDFTag = SkPDF::StructureElementNode;
30
31 // Test building a tagged PDF where nodes are pruned.
32 // Add this to args.gn to output the PDF to a file:
33 // extra_cflags = [ "-DSK_PDF_TEST_TAGS_OUTPUT_PATH=\"/tmp/pruning.pdf\"" ]
DEF_TEST(SkPDF_tagged_pruning,r)34 DEF_TEST(SkPDF_tagged_pruning, 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 PDF";
46 metadata.fCreator = "Skia";
47 SkTime::DateTime now;
48 SkTime::GetDateTime(&now);
49 metadata.fCreation = now;
50 metadata.fModified = now;
51
52 // The document tag.
53 auto root = std::make_unique<PDFTag>();
54 root->fNodeId = 1;
55 root->fTypeString = "Document";
56 root->fLang = "en-US";
57
58 // First paragraph.
59 auto p1 = std::make_unique<PDFTag>();
60 p1->fNodeId = 2;
61 p1->fAdditionalNodeIds = {3, 4};
62 p1->fTypeString = "P";
63 root->fChildVector.push_back(std::move(p1));
64
65 // Second paragraph.
66 auto p2 = std::make_unique<PDFTag>();
67 p2->fNodeId = 5;
68 p2->fAdditionalNodeIds = {6, 7};
69 p2->fTypeString = "P";
70 root->fChildVector.push_back(std::move(p2));
71
72 metadata.fStructureElementTreeRoot = root.get();
73 sk_sp<SkDocument> document = SkPDF::MakeDocument(
74 &outputStream, metadata);
75
76 SkPaint paint;
77 paint.setColor(SK_ColorBLACK);
78
79 SkCanvas* canvas =
80 document->beginPage(pageSize.width(),
81 pageSize.height());
82 SkFont font(nullptr, 20);
83 SkPDF::SetNodeId(canvas, 3);
84 canvas->drawString("First paragraph line 1", 72, 72, font, paint);
85 SkPDF::SetNodeId(canvas, 4);
86 canvas->drawString("First paragraph line 2", 72, 108, font, paint);
87 SkPDF::SetNodeId(canvas, 6);
88 canvas->drawString("Second paragraph line 1", 72, 180, font, paint);
89 SkPDF::SetNodeId(canvas, 7);
90 canvas->drawString("Second paragraph line 2", 72, 216, font, paint);
91
92 document->endPage();
93 document->close();
94 outputStream.flush();
95 }
96
97 // Similar to SkPDF_tagged_pruning but never actually writes out anything annotated.
98 // Ensures that nothing goes wring when there are no annotations on an annotated PDF.
DEF_TEST(SkPDF_tagged_pruning_empty,r)99 DEF_TEST(SkPDF_tagged_pruning_empty, r) {
100 REQUIRE_PDF_DOCUMENT(SkPDF_tagged, r);
101 #ifdef SK_PDF_TEST_TAGS_OUTPUT_PATH
102 SkFILEWStream outputStream(SK_PDF_TEST_TAGS_OUTPUT_PATH);
103 #else
104 SkDynamicMemoryWStream outputStream;
105 #endif
106
107 SkSize pageSize = SkSize::Make(612, 792); // U.S. Letter
108
109 SkPDF::Metadata metadata;
110 metadata.fTitle = "Example Tagged PDF";
111 metadata.fCreator = "Skia";
112 SkTime::DateTime now;
113 SkTime::GetDateTime(&now);
114 metadata.fCreation = now;
115 metadata.fModified = now;
116
117 // The document tag.
118 auto root = std::make_unique<PDFTag>();
119 root->fNodeId = 1;
120 root->fTypeString = "Document";
121 root->fLang = "en-US";
122
123 // First paragraph.
124 auto p1 = std::make_unique<PDFTag>();
125 p1->fNodeId = 2;
126 p1->fAdditionalNodeIds = {3, 4};
127 p1->fTypeString = "P";
128 root->fChildVector.push_back(std::move(p1));
129
130 // Second paragraph.
131 auto p2 = std::make_unique<PDFTag>();
132 p2->fNodeId = 5;
133 p2->fAdditionalNodeIds = {6, 7};
134 p2->fTypeString = "P";
135 root->fChildVector.push_back(std::move(p2));
136
137 metadata.fStructureElementTreeRoot = root.get();
138 sk_sp<SkDocument> document = SkPDF::MakeDocument(
139 &outputStream, metadata);
140
141 SkPaint paint;
142 paint.setColor(SK_ColorBLACK);
143
144 SkCanvas* canvas =
145 document->beginPage(pageSize.width(),
146 pageSize.height());
147
148 canvas->drawRect(SkRect::MakeXYWH(10, 10, 100, 100), paint);
149
150 document->endPage();
151 document->close();
152 outputStream.flush();
153 }
154
155 #endif
156