xref: /aosp_15_r20/external/skia/src/pdf/SkPDFTag.h (revision c8dee2aa9b3f27cf6c858bd81872bdeb2c07ed17)
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 
21 class SkPDFDocument;
22 struct SkPDFStructElem;
23 struct SkPoint;
24 
25 class SkPDFStructTree {
26 public:
27     SkPDFStructTree(SkPDF::StructureElementNode*, SkPDF::Metadata::Outline);
28     SkPDFStructTree(const SkPDFStructTree&) = delete;
29     SkPDFStructTree& operator=(const SkPDFStructTree&) = delete;
30     SkPDFStructTree(SkPDFStructTree&&) = delete;
31     SkPDFStructTree& operator=(SkPDFStructTree&&) = delete;
32     ~SkPDFStructTree();
33 
34     class Mark {
35         SkPDFStructElem* fStructElem;
36         size_t fMarkIndex;
37     public:
Mark(SkPDFStructElem * structElem,size_t markIndex)38         Mark(SkPDFStructElem* structElem, size_t markIndex)
39             : fStructElem(structElem), fMarkIndex(markIndex) {}
Mark()40         Mark() : Mark(nullptr, 0) {}
41         Mark(const Mark&) = default;
42         Mark& operator=(const Mark&) = default;
43         Mark(Mark&&) = default;
44         Mark& operator=(Mark&&) = default;
45 
46         explicit operator bool() const { return fStructElem; }
47         int mcid() const; // mcid < 0 means no active mark, if bool(this) always >= 0
48         int elemId() const; // 0 elemId means no active structure element
49         SkString structType() const; // only call when bool(this)
50         void accumulate(SkPoint); // only call when bool(this)
51     };
52 
53     // Create a new marked-content identifier (MCID) to be used with a marked-content sequence
54     // parented by the structure element (StructElem) with the given element identifier (elemId).
55     // The StructTreeRoot::ParentTree[Page::StructParent][mcid] will refer to the structure element.
56     // The structure element will add this MCID as its next child (in StructElem::K).
57     // Returns a false Mark if if elemId does not refer to a StructElem.
58     SkPDFStructTree::Mark createMarkForElemId(int elemId, unsigned pageIndex);
59 
60     // Create a key to use with /StructParent in a content item (usually an annotation) which refers
61     // to the structure element (StructElem) with the given element identifier (elemId).
62     // The StructTreeRoot ParentTree will map from this key to the structure element.
63     // The structure element will add the content item as its next child (as StructElem::K::OBJR).
64     // Returns -1 if elemId does not refer to a StructElem.
65     int createStructParentKeyForElemId(int elemId, SkPDFIndirectReference contentItemRef,
66                                        unsigned pageIndex);
67 
68     void addStructElemTitle(int elemId, SkSpan<const char>);
69     SkPDFIndirectReference emitStructTreeRoot(SkPDFDocument* doc) const;
70     SkPDFIndirectReference makeOutline(SkPDFDocument* doc) const;
71     SkString getRootLanguage();
72 
73     // An entry in an ordered map from an element identifier to an indirect reference to its
74     // corresponding structure element.
75     struct IDTreeEntry {
76         int elemId;
77         SkPDFIndirectReference structElemRef;
78     };
79 private:
80     void move(SkPDF::StructureElementNode& node, SkPDFStructElem* structElem, bool wantTitle);
81 
82     SkArenaAlloc fArena;
83     skia_private::THashMap<int, SkPDFStructElem*> fStructElemForElemId;
84     SkPDFStructElem* fRoot = nullptr;
85     SkPDF::Metadata::Outline fOutline = SkPDF::Metadata::Outline::None;
86     // fStructElemForMcidForPage[Page::StructParents][mcid] -> parent StructElem of mcid
87     skia_private::TArray<skia_private::TArray<SkPDFStructElem*>> fStructElemForMcidForPage;
88     // fStructElemForContentItem[?::StructParent] -> parent StructElem of content-item
89     skia_private::TArray<SkPDFStructElem*> fStructElemForContentItem;
90 };
91 
92 #endif
93