/* * Copyright 2018 Google Inc. * * Use of this source code is governed by a BSD-style license that can be * found in the LICENSE file. */ #include "Test.h" #include "SkCanvas.h" #include "SkPDFDocument.h" #include "SkStream.h" #include "SkFont.h" using PDFTag = SkPDF::StructureElementNode; // Test building a tagged PDF. // Add this to args.gn to output the PDF to a file: // extra_cflags = [ "-DSK_PDF_TEST_TAGS_OUTPUT_PATH=\"/tmp/foo.pdf\"" ] DEF_TEST(SkPDF_tagged, r) { REQUIRE_PDF_DOCUMENT(SkPDF_tagged, r); #ifdef SK_PDF_TEST_TAGS_OUTPUT_PATH SkFILEWStream outputStream(SK_PDF_TEST_TAGS_OUTPUT_PATH); #else SkDynamicMemoryWStream outputStream; #endif SkSize pageSize = SkSize::Make(612, 792); // U.S. Letter SkPDF::Metadata metadata; metadata.fTitle = "Example Tagged PDF"; metadata.fCreator = "Skia"; SkTime::DateTime now; SkTime::GetDateTime(&now); metadata.fCreation = now; metadata.fModified = now; // The document tag. PDFTag root; root.fNodeId = 1; root.fType = SkPDF::DocumentStructureType::kDocument; root.fChildCount = 5; PDFTag rootChildren[5]; root.fChildren = rootChildren; // Heading. PDFTag& h1 = rootChildren[0]; h1.fNodeId = 2; h1.fType = SkPDF::DocumentStructureType::kH1; h1.fChildCount = 0; // Initial paragraph. PDFTag& p = rootChildren[1]; p.fNodeId = 3; p.fType = SkPDF::DocumentStructureType::kP; p.fChildCount = 0; // Hidden div. This is never referenced by marked content // so it should not appear in the resulting PDF. PDFTag& div = rootChildren[2]; div.fNodeId = 4; div.fType = SkPDF::DocumentStructureType::kDiv; div.fChildCount = 0; // A bulleted list of two items. PDFTag& l = rootChildren[3]; l.fNodeId = 5; l.fType = SkPDF::DocumentStructureType::kL; l.fChildCount = 4; PDFTag listChildren[4]; l.fChildren = listChildren; PDFTag& lm1 = listChildren[0]; lm1.fNodeId = 6; lm1.fType = SkPDF::DocumentStructureType::kLbl; lm1.fChildCount = 0; PDFTag& li1 = listChildren[1]; li1.fNodeId = 7; li1.fType = SkPDF::DocumentStructureType::kLI; li1.fChildCount = 0; PDFTag& lm2 = listChildren[2]; lm2.fNodeId = 8; lm2.fType = SkPDF::DocumentStructureType::kLbl; lm2.fChildCount = 0; PDFTag& li2 = listChildren[3]; li2.fNodeId = 9; li2.fType = SkPDF::DocumentStructureType::kLI; li2.fChildCount = 0; // Paragraph spanning two pages. PDFTag& p2 = rootChildren[4]; p2.fNodeId = 10; p2.fType = SkPDF::DocumentStructureType::kP; p2.fChildCount = 0; metadata.fStructureElementTreeRoot = &root; sk_sp<SkDocument> document = SkPDF::MakeDocument( &outputStream, metadata); SkPaint paint; paint.setColor(SK_ColorBLACK); // First page. SkCanvas* canvas = document->beginPage(pageSize.width(), pageSize.height()); SkPDF::SetNodeId(canvas, 2); SkFont font(nullptr, 36); const char* message = "This is the title"; canvas->translate(72, 72); canvas->drawString(message, 0, 0, font, paint); SkPDF::SetNodeId(canvas, 3); font.setSize(14); message = "This is a simple paragraph."; canvas->translate(0, 72); canvas->drawString(message, 0, 0, font, paint); SkPDF::SetNodeId(canvas, 6); font.setSize(14); message = "*"; canvas->translate(0, 72); canvas->drawString(message, 0, 0, font, paint); SkPDF::SetNodeId(canvas, 7); message = "List item 1"; canvas->translate(36, 0); canvas->drawString(message, 0, 0, font, paint); SkPDF::SetNodeId(canvas, 8); message = "*"; canvas->translate(-36, 36); canvas->drawString(message, 0, 0, font, paint); SkPDF::SetNodeId(canvas, 9); message = "List item 2"; canvas->translate(36, 0); canvas->drawString(message, 0, 0, font, paint); SkPDF::SetNodeId(canvas, 10); message = "This is a paragraph that starts on one page"; canvas->translate(-36, 6 * 72); canvas->drawString(message, 0, 0, font, paint); document->endPage(); // Second page. canvas = document->beginPage(pageSize.width(), pageSize.height()); SkPDF::SetNodeId(canvas, 10); message = "and finishes on the second page."; canvas->translate(72, 72); canvas->drawString(message, 0, 0, font, paint); // This has a node ID but never shows up in the tag tree so it // won't be tagged. SkPDF::SetNodeId(canvas, 999); message = "Page 2"; canvas->translate(468, -36); canvas->drawString(message, 0, 0, font, paint); document->endPage(); document->close(); outputStream.flush(); }