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