C++程序  |  168行  |  4.64 KB

/*
 * 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();
}