• 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 
8 #ifndef SkPDFTag_DEFINED
9 #define SkPDFTag_DEFINED
10 
11 #include "include/core/SkSpan.h"
12 #include "include/core/SkString.h"
13 #include "include/docs/SkPDFDocument.h"
14 #include "include/private/base/SkTArray.h"
15 #include "src/base/SkArenaAlloc.h"
16 #include "src/core/SkTHash.h"
17 #include "src/pdf/SkPDFTypes.h"
18 
19 #include <cstddef>
20 #include <vector>
21 
22 class SkPDFDocument;
23 struct SkPDFTagNode;
24 struct SkPoint;
25 
26 class SkPDFTagTree {
27 public:
28     SkPDFTagTree();
29     ~SkPDFTagTree();
30     void init(SkPDF::StructureElementNode*, SkPDF::Metadata::Outline);
31 
32     class Mark {
33         SkPDFTagNode *const fNode;
34         size_t const fMarkIndex;
35     public:
Mark(SkPDFTagNode * node,size_t index)36         Mark(SkPDFTagNode* node, size_t index) : fNode(node), fMarkIndex(index) {}
Mark()37         Mark() : Mark(nullptr, 0) {}
38         Mark(const Mark&) = delete;
39         Mark& operator=(const Mark&) = delete;
40         Mark(Mark&&) = default;
41         Mark& operator=(Mark&&) = delete;
42 
43         explicit operator bool() const { return fNode; }
44         int id();
45         SkPoint& point();
46     };
47     // Used to allow marked content to refer to its corresponding structure
48     // tree node, via a page entry in the parent tree. Returns a false mark if
49     // nodeId is 0.
50     Mark createMarkIdForNodeId(int nodeId, unsigned pageIndex, SkPoint);
51     // Used to allow annotations to refer to their corresponding structure
52     // tree node, via the struct parent tree. Returns -1 if no struct parent
53     // key.
54     int createStructParentKeyForNodeId(int nodeId, unsigned pageIndex);
55 
56     void addNodeAnnotation(int nodeId, SkPDFIndirectReference annotationRef, unsigned pageIndex);
57     void addNodeTitle(int nodeId, SkSpan<const char>);
58     SkPDFIndirectReference makeStructTreeRoot(SkPDFDocument* doc);
59     SkPDFIndirectReference makeOutline(SkPDFDocument* doc);
60     SkString getRootLanguage();
61 
62 private:
63     // An entry in a map from a node ID to an indirect reference to its
64     // corresponding structure element node.
65     struct IDTreeEntry {
66         int nodeId;
67         SkPDFIndirectReference ref;
68     };
69 
70     void Copy(SkPDF::StructureElementNode& node,
71               SkPDFTagNode* dst,
72               SkArenaAlloc* arena,
73               skia_private::THashMap<int, SkPDFTagNode*>* nodeMap,
74               bool wantTitle);
75     SkPDFIndirectReference PrepareTagTreeToEmit(SkPDFIndirectReference parent,
76                                                 SkPDFTagNode* node,
77                                                 SkPDFDocument* doc);
78 
79     SkArenaAlloc fArena;
80     skia_private::THashMap<int, SkPDFTagNode*> fNodeMap;
81     SkPDFTagNode* fRoot = nullptr;
82     SkPDF::Metadata::Outline fOutline;
83     skia_private::TArray<skia_private::TArray<SkPDFTagNode*>> fMarksPerPage;
84     std::vector<IDTreeEntry> fIdTreeEntries;
85     std::vector<int> fParentTreeAnnotationNodeIds;
86 
87     SkPDFTagTree(const SkPDFTagTree&) = delete;
88     SkPDFTagTree& operator=(const SkPDFTagTree&) = delete;
89 };
90 
91 #endif
92