• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright 2018 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 #include "include/core/SkBitmap.h"
10 #include "include/core/SkCanvas.h"
11 #include "include/core/SkFont.h"
12 #include "include/core/SkStream.h"
13 #include "include/docs/SkPDFDocument.h"
14 
15 using PDFTag = SkPDF::StructureElementNode;
16 
17 // Test building a tagged PDF.
18 // Add this to args.gn to output the PDF to a file:
19 //   extra_cflags = [ "-DSK_PDF_TEST_TAGS_OUTPUT_PATH=\"/tmp/foo.pdf\"" ]
DEF_TEST(SkPDF_tagged_doc,r)20 DEF_TEST(SkPDF_tagged_doc, r) {
21     REQUIRE_PDF_DOCUMENT(SkPDF_tagged_doc, r);
22 #ifdef SK_PDF_TEST_TAGS_OUTPUT_PATH
23     SkFILEWStream outputStream(SK_PDF_TEST_TAGS_OUTPUT_PATH);
24 #else
25     SkDynamicMemoryWStream outputStream;
26 #endif
27 
28     SkSize pageSize = SkSize::Make(612, 792);  // U.S. Letter
29 
30     SkPDF::Metadata metadata;
31     metadata.fTitle = "Example Tagged PDF";
32     metadata.fCreator = "Skia";
33     SkTime::DateTime now;
34     SkTime::GetDateTime(&now);
35     metadata.fCreation = now;
36     metadata.fModified = now;
37 
38     // The document tag.
39     auto root = std::make_unique<PDFTag>();
40     root->fNodeId = 1;
41     root->fTypeString = "Document";
42 
43     // Heading.
44     auto h1 = std::make_unique<PDFTag>();
45     h1->fNodeId = 2;
46     h1->fTypeString = "H1";
47     root->fChildVector.push_back(std::move(h1));
48 
49     // Initial paragraph.
50     auto p = std::make_unique<PDFTag>();
51     p->fNodeId = 3;
52     p->fTypeString = "P";
53     root->fChildVector.push_back(std::move(p));
54 
55     // Hidden div. This is never referenced by marked content
56     // so it should not appear in the resulting PDF.
57     auto div = std::make_unique<PDFTag>();
58     div->fNodeId = 4;
59     div->fTypeString = "Div";
60     root->fChildVector.push_back(std::move(div));
61 
62     // A bulleted list of two items.
63     auto l = std::make_unique<PDFTag>();
64     l->fNodeId = 5;
65     l->fTypeString = "L";
66 
67     auto lm1 = std::make_unique<PDFTag>();
68     lm1->fNodeId = 6;
69     lm1->fTypeString = "Lbl";
70     l->fChildVector.push_back(std::move(lm1));
71 
72     auto li1 = std::make_unique<PDFTag>();
73     li1->fNodeId = 7;
74     li1->fTypeString = "LI";
75     l->fChildVector.push_back(std::move(li1));
76 
77     auto lm2 = std::make_unique<PDFTag>();
78     lm2->fNodeId = 8;
79     lm2->fTypeString = "Lbl";
80     l->fChildVector.push_back(std::move(lm2));
81     auto li2 = std::make_unique<PDFTag>();
82     li2->fNodeId = 9;
83     li2->fTypeString = "LI";
84     l->fChildVector.push_back(std::move(li2));
85 
86     root->fChildVector.push_back(std::move(l));
87 
88     // Paragraph spanning two pages.
89     auto p2 = std::make_unique<PDFTag>();
90     p2->fNodeId = 10;
91     p2->fTypeString = "P";
92     root->fChildVector.push_back(std::move(p2));
93 
94     // Image with alt text.
95     auto img = std::make_unique<PDFTag>();
96     img->fNodeId = 11;
97     img->fTypeString = "Figure";
98     img->fAlt = "Red box";
99     root->fChildVector.push_back(std::move(img));
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     // First page.
109     SkCanvas* canvas =
110             document->beginPage(pageSize.width(),
111                                 pageSize.height());
112     SkPDF::SetNodeId(canvas, 2);
113     SkFont font(nullptr, 36);
114     const char* message = "This is the title";
115     canvas->translate(72, 72);
116     canvas->drawString(message, 0, 0, font, paint);
117 
118     SkPDF::SetNodeId(canvas, 3);
119     font.setSize(14);
120     message = "This is a simple paragraph.";
121     canvas->translate(0, 72);
122     canvas->drawString(message, 0, 0, font, paint);
123 
124     SkPDF::SetNodeId(canvas, 6);
125     font.setSize(14);
126     message = "*";
127     canvas->translate(0, 72);
128     canvas->drawString(message, 0, 0, font, paint);
129 
130     SkPDF::SetNodeId(canvas, 7);
131     message = "List item 1";
132     canvas->translate(36, 0);
133     canvas->drawString(message, 0, 0, font, paint);
134 
135     SkPDF::SetNodeId(canvas, 8);
136     message = "*";
137     canvas->translate(-36, 36);
138     canvas->drawString(message, 0, 0, font, paint);
139 
140     SkPDF::SetNodeId(canvas, 9);
141     message = "List item 2";
142     canvas->translate(36, 0);
143     canvas->drawString(message, 0, 0, font, paint);
144 
145     SkPDF::SetNodeId(canvas, 10);
146     message = "This is a paragraph that starts on one page";
147     canvas->translate(-36, 6 * 72);
148     canvas->drawString(message, 0, 0, font, paint);
149 
150     document->endPage();
151 
152     // Second page.
153     canvas = document->beginPage(pageSize.width(),
154                                  pageSize.height());
155     SkPDF::SetNodeId(canvas, 10);
156     message = "and finishes on the second page.";
157     canvas->translate(72, 72);
158     canvas->drawString(message, 0, 0, font, paint);
159 
160     // Test a tagged image with alt text.
161     SkPDF::SetNodeId(canvas, 11);
162     SkBitmap testBitmap;
163     testBitmap.allocN32Pixels(72, 72);
164     testBitmap.eraseColor(SK_ColorRED);
165     canvas->translate(72, 72);
166     canvas->drawImage(testBitmap.asImage(), 0, 0);
167 
168     // This has a node ID but never shows up in the tag tree so it
169     // won't be tagged.
170     SkPDF::SetNodeId(canvas, 999);
171     message = "Page 2";
172     canvas->translate(468, -36);
173     canvas->drawString(message, 0, 0, font, paint);
174 
175     document->endPage();
176 
177     document->close();
178 
179     outputStream.flush();
180 }
181