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