PDFTaggedTest.cpp 4.7 KB

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