• 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 "Test.h"
8 
9 #include "SkCanvas.h"
10 #include "SkPDFDocument.h"
11 #include "SkStream.h"
12 #include "SkFont.h"
13 
14 using PDFTag = SkPDF::StructureElementNode;
15 
16 // Test building a tagged PDF.
17 // Add this to args.gn to output the PDF to a file:
18 //   extra_cflags = [ "-DSK_PDF_TEST_TAGS_OUTPUT_PATH=\"/tmp/foo.pdf\"" ]
DEF_TEST(SkPDF_tagged,r)19 DEF_TEST(SkPDF_tagged, r) {
20     REQUIRE_PDF_DOCUMENT(SkPDF_tagged, r);
21 #ifdef SK_PDF_TEST_TAGS_OUTPUT_PATH
22     SkFILEWStream outputStream(SK_PDF_TEST_TAGS_OUTPUT_PATH);
23 #else
24     SkDynamicMemoryWStream outputStream;
25 #endif
26 
27     SkSize pageSize = SkSize::Make(612, 792);  // U.S. Letter
28 
29     SkPDF::Metadata metadata;
30     metadata.fTitle = "Example Tagged PDF";
31     metadata.fCreator = "Skia";
32     SkTime::DateTime now;
33     SkTime::GetDateTime(&now);
34     metadata.fCreation = now;
35     metadata.fModified = now;
36 
37     // The document tag.
38     PDFTag root;
39     root.fNodeId = 1;
40     root.fType = SkPDF::DocumentStructureType::kDocument;
41     root.fChildCount = 5;
42     PDFTag rootChildren[5];
43     root.fChildren = rootChildren;
44 
45     // Heading.
46     PDFTag& h1 = rootChildren[0];
47     h1.fNodeId = 2;
48     h1.fType = SkPDF::DocumentStructureType::kH1;
49     h1.fChildCount = 0;
50 
51     // Initial paragraph.
52     PDFTag& p = rootChildren[1];
53     p.fNodeId = 3;
54     p.fType = SkPDF::DocumentStructureType::kP;
55     p.fChildCount = 0;
56 
57     // Hidden div. This is never referenced by marked content
58     // so it should not appear in the resulting PDF.
59     PDFTag& div = rootChildren[2];
60     div.fNodeId = 4;
61     div.fType = SkPDF::DocumentStructureType::kDiv;
62     div.fChildCount = 0;
63 
64     // A bulleted list of two items.
65     PDFTag& l = rootChildren[3];
66     l.fNodeId = 5;
67     l.fType = SkPDF::DocumentStructureType::kL;
68     l.fChildCount = 4;
69     PDFTag listChildren[4];
70     l.fChildren = listChildren;
71 
72     PDFTag& lm1 = listChildren[0];
73     lm1.fNodeId = 6;
74     lm1.fType = SkPDF::DocumentStructureType::kLbl;
75     lm1.fChildCount = 0;
76     PDFTag& li1 = listChildren[1];
77     li1.fNodeId = 7;
78     li1.fType = SkPDF::DocumentStructureType::kLI;
79     li1.fChildCount = 0;
80 
81     PDFTag& lm2 = listChildren[2];
82     lm2.fNodeId = 8;
83     lm2.fType = SkPDF::DocumentStructureType::kLbl;
84     lm2.fChildCount = 0;
85     PDFTag& li2 = listChildren[3];
86     li2.fNodeId = 9;
87     li2.fType = SkPDF::DocumentStructureType::kLI;
88     li2.fChildCount = 0;
89 
90     // Paragraph spanning two pages.
91     PDFTag& p2 = rootChildren[4];
92     p2.fNodeId = 10;
93     p2.fType = SkPDF::DocumentStructureType::kP;
94     p2.fChildCount = 0;
95 
96     metadata.fStructureElementTreeRoot = &root;
97     sk_sp<SkDocument> document = SkPDF::MakeDocument(
98         &outputStream, metadata);
99 
100     SkPaint paint;
101     paint.setColor(SK_ColorBLACK);
102 
103     // First page.
104     SkCanvas* canvas =
105             document->beginPage(pageSize.width(),
106                                 pageSize.height());
107     SkPDF::SetNodeId(canvas, 2);
108     SkFont font(nullptr, 36);
109     const char* message = "This is the title";
110     canvas->translate(72, 72);
111     canvas->drawString(message, 0, 0, font, paint);
112 
113     SkPDF::SetNodeId(canvas, 3);
114     font.setSize(14);
115     message = "This is a simple paragraph.";
116     canvas->translate(0, 72);
117     canvas->drawString(message, 0, 0, font, paint);
118 
119     SkPDF::SetNodeId(canvas, 6);
120     font.setSize(14);
121     message = "*";
122     canvas->translate(0, 72);
123     canvas->drawString(message, 0, 0, font, paint);
124 
125     SkPDF::SetNodeId(canvas, 7);
126     message = "List item 1";
127     canvas->translate(36, 0);
128     canvas->drawString(message, 0, 0, font, paint);
129 
130     SkPDF::SetNodeId(canvas, 8);
131     message = "*";
132     canvas->translate(-36, 36);
133     canvas->drawString(message, 0, 0, font, paint);
134 
135     SkPDF::SetNodeId(canvas, 9);
136     message = "List item 2";
137     canvas->translate(36, 0);
138     canvas->drawString(message, 0, 0, font, paint);
139 
140     SkPDF::SetNodeId(canvas, 10);
141     message = "This is a paragraph that starts on one page";
142     canvas->translate(-36, 6 * 72);
143     canvas->drawString(message, 0, 0, font, paint);
144 
145     document->endPage();
146 
147     // Second page.
148     canvas = document->beginPage(pageSize.width(),
149                                  pageSize.height());
150     SkPDF::SetNodeId(canvas, 10);
151     message = "and finishes on the second page.";
152     canvas->translate(72, 72);
153     canvas->drawString(message, 0, 0, font, paint);
154 
155     // This has a node ID but never shows up in the tag tree so it
156     // won't be tagged.
157     SkPDF::SetNodeId(canvas, 999);
158     message = "Page 2";
159     canvas->translate(468, -36);
160     canvas->drawString(message, 0, 0, font, paint);
161 
162     document->endPage();
163 
164     document->close();
165 
166     outputStream.flush();
167 }
168