Flutter Engine
The Flutter Engine
All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Properties Friends Macros Modules Pages
Classes | Public Member Functions | List of all members
SkPDFTagTree Class Reference

#include <SkPDFTag.h>

Classes

class  Mark
 

Public Member Functions

 SkPDFTagTree ()
 
 ~SkPDFTagTree ()
 
void init (SkPDF::StructureElementNode *, SkPDF::Metadata::Outline)
 
Mark createMarkIdForNodeId (int nodeId, unsigned pageIndex, SkPoint)
 
int createStructParentKeyForNodeId (int nodeId, unsigned pageIndex)
 
void addNodeAnnotation (int nodeId, SkPDFIndirectReference annotationRef, unsigned pageIndex)
 
void addNodeTitle (int nodeId, SkSpan< const char >)
 
SkPDFIndirectReference makeStructTreeRoot (SkPDFDocument *doc)
 
SkPDFIndirectReference makeOutline (SkPDFDocument *doc)
 
SkString getRootLanguage ()
 

Detailed Description

Definition at line 26 of file SkPDFTag.h.

Constructor & Destructor Documentation

◆ SkPDFTagTree()

SkPDFTagTree::SkPDFTagTree ( )

Definition at line 164 of file SkPDFTag.cpp.

164: fArena(4 * sizeof(SkPDFTagNode)) {}

◆ ~SkPDFTagTree()

SkPDFTagTree::~SkPDFTagTree ( )
default

Member Function Documentation

◆ addNodeAnnotation()

void SkPDFTagTree::addNodeAnnotation ( int  nodeId,
SkPDFIndirectReference  annotationRef,
unsigned  pageIndex 
)

Definition at line 329 of file SkPDFTag.cpp.

329 {
330 if (!fRoot) {
331 return;
332 }
333 SkPDFTagNode** tagPtr = fNodeMap.find(nodeId);
334 if (!tagPtr) {
335 return;
336 }
337 SkPDFTagNode* tag = *tagPtr;
338 SkASSERT(tag);
339
340 SkPDFTagNode::AnnotationInfo annotationInfo = {pageIndex, annotationRef};
341 tag->fAnnotations.push_back(annotationInfo);
342}
#define SkASSERT(cond)
Definition: SkAssert.h:116
V * find(const K &key) const
Definition: SkTHash.h:494
std::vector< AnnotationInfo > fAnnotations
Definition: SkPDFTag.cpp:96

◆ addNodeTitle()

void SkPDFTagTree::addNodeTitle ( int  nodeId,
SkSpan< const char >  title 
)

Definition at line 344 of file SkPDFTag.cpp.

344 {
345 if (!fRoot) {
346 return;
347 }
348 SkPDFTagNode** tagPtr = fNodeMap.find(nodeId);
349 if (!tagPtr) {
350 return;
351 }
352 SkPDFTagNode* tag = *tagPtr;
353 SkASSERT(tag);
354
355 if (tag->fWantTitle) {
356 tag->fTitle.append(title.data(), title.size());
357 // Arbitrary cutoff for size.
358 if (tag->fTitle.size() > 1023) {
359 tag->fWantTitle = false;
360 }
361 }
362}
constexpr T * data() const
Definition: SkSpan_impl.h:94
constexpr size_t size() const
Definition: SkSpan_impl.h:95
size_t size() const
Definition: SkString.h:131
void append(const char text[])
Definition: SkString.h:203
SkString fTitle
Definition: SkPDFTag.cpp:82
bool fWantTitle
Definition: SkPDFTag.cpp:80

◆ createMarkIdForNodeId()

auto SkPDFTagTree::createMarkIdForNodeId ( int  nodeId,
unsigned  pageIndex,
SkPoint  point 
)

Definition at line 218 of file SkPDFTag.cpp.

218 {
219 if (!fRoot) {
220 return Mark();
221 }
222 SkPDFTagNode** tagPtr = fNodeMap.find(nodeId);
223 if (!tagPtr) {
224 return Mark();
225 }
226 SkPDFTagNode* tag = *tagPtr;
227 SkASSERT(tag);
228 while (SkToUInt(fMarksPerPage.size()) < pageIndex + 1) {
229 fMarksPerPage.push_back();
230 }
231 TArray<SkPDFTagNode*>& pageMarks = fMarksPerPage[pageIndex];
232 int markId = pageMarks.size();
233 tag->fMarkedContent.push_back({{point, pageIndex}, markId});
234 pageMarks.push_back(tag);
235 return Mark(tag, tag->fMarkedContent.size() - 1);
236}
constexpr unsigned SkToUInt(S x)
Definition: SkTo.h:30
int size() const
Definition: SkTArray.h:421
TArray< MarkedContentInfo > fMarkedContent
Definition: SkPDFTag.cpp:78

◆ createStructParentKeyForNodeId()

int SkPDFTagTree::createStructParentKeyForNodeId ( int  nodeId,
unsigned  pageIndex 
)

Definition at line 238 of file SkPDFTag.cpp.

238 {
239 if (!fRoot) {
240 return -1;
241 }
242 SkPDFTagNode** tagPtr = fNodeMap.find(nodeId);
243 if (!tagPtr) {
244 return -1;
245 }
246 SkPDFTagNode* tag = *tagPtr;
247 SkASSERT(tag);
248
250
251 int nextStructParentKey = kFirstAnnotationStructParentKey +
252 static_cast<int>(fParentTreeAnnotationNodeIds.size());
253 fParentTreeAnnotationNodeIds.push_back(nodeId);
254 return nextStructParentKey;
255}
const int kFirstAnnotationStructParentKey
Definition: SkPDFTag.cpp:32
enum SkPDFTagNode::State fCanDiscard

◆ getRootLanguage()

SkString SkPDFTagTree::getRootLanguage ( )

Definition at line 583 of file SkPDFTag.cpp.

583 {
584 return fRoot ? fRoot->fLang : SkString();
585}
SkString fLang
Definition: SkPDFTag.cpp:84

◆ init()

void SkPDFTagTree::init ( SkPDF::StructureElementNode node,
SkPDF::Metadata::Outline  outline 
)

Definition at line 202 of file SkPDFTag.cpp.

202 {
203 if (node) {
204 fRoot = fArena.make<SkPDFTagNode>();
205 fOutline = outline;
206 Copy(*node, fRoot, &fArena, &fNodeMap, false);
207 }
208}
auto make(Ctor &&ctor) -> decltype(ctor(nullptr))
Definition: SkArenaAlloc.h:120

◆ makeOutline()

SkPDFIndirectReference SkPDFTagTree::makeOutline ( SkPDFDocument doc)

Definition at line 559 of file SkPDFTag.cpp.

559 {
560 if (!fRoot || can_discard(fRoot) ||
562 {
563 return SkPDFIndirectReference();
564 }
565
567 OutlineEntry top{{SkString(), Location()}, 0, {}, {}};
568 stack.push_back(&top);
569 create_outline_from_headers(doc, fRoot, stack);
570 if (top.fChildren.empty()) {
571 return SkPDFIndirectReference();
572 }
573 top.emitDescendents(doc);
574 SkPDFIndirectReference outlineRef = doc->reserveRef();
575 SkPDFDict outline("Outlines");
576 outline.insertRef("First", top.fChildren.front().fRef);
577 outline.insertRef("Last", top.fChildren.back().fRef);
578 outline.insertInt("Count", top.fDescendentsEmitted);
579
580 return doc->emit(outline, outlineRef);
581}
static bool can_discard(SkPDFTagNode *node)
Definition: SkPDFTag.cpp:257
SkPDFIndirectReference emit(const SkPDFObject &, SkPDFIndirectReference)
SkPDFIndirectReference reserveRef()

◆ makeStructTreeRoot()

SkPDFIndirectReference SkPDFTagTree::makeStructTreeRoot ( SkPDFDocument doc)

Definition at line 364 of file SkPDFTag.cpp.

364 {
365 if (!fRoot || can_discard(fRoot)) {
366 return SkPDFIndirectReference();
367 }
368
370
371 unsigned pageCount = SkToUInt(doc->pageCount());
372
373 // Build the StructTreeRoot.
374 SkPDFDict structTreeRoot("StructTreeRoot");
375 structTreeRoot.insertRef("K", PrepareTagTreeToEmit(ref, fRoot, doc));
376 structTreeRoot.insertInt("ParentTreeNextKey", SkToInt(pageCount));
377
378 // Build the parent tree, which consists of two things:
379 // (1) For each page, a mapping from the marked content IDs on
380 // each page to their corresponding tags
381 // (2) For each annotation, an indirect reference to that
382 // annotation's struct tree element.
383 SkPDFDict parentTree("ParentTree");
384 auto parentTreeNums = SkPDFMakeArray();
385
386 // First, one entry per page.
387 SkASSERT(SkToUInt(fMarksPerPage.size()) <= pageCount);
388 for (int j = 0; j < fMarksPerPage.size(); ++j) {
389 const TArray<SkPDFTagNode*>& pageMarks = fMarksPerPage[j];
390 SkPDFArray markToTagArray;
391 for (SkPDFTagNode* mark : pageMarks) {
392 SkASSERT(mark->fRef);
393 markToTagArray.appendRef(mark->fRef);
394 }
395 parentTreeNums->appendInt(j);
396 parentTreeNums->appendRef(doc->emit(markToTagArray));
397 }
398
399 // Then, one entry per annotation.
400 for (size_t j = 0; j < fParentTreeAnnotationNodeIds.size(); ++j) {
401 int nodeId = fParentTreeAnnotationNodeIds[j];
402 int structParentKey = kFirstAnnotationStructParentKey + static_cast<int>(j);
403
404 SkPDFTagNode** tagPtr = fNodeMap.find(nodeId);
405 if (!tagPtr) {
406 continue;
407 }
408 SkPDFTagNode* tag = *tagPtr;
409 parentTreeNums->appendInt(structParentKey);
410 parentTreeNums->appendRef(tag->fRef);
411 }
412
413 parentTree.insertObject("Nums", std::move(parentTreeNums));
414 structTreeRoot.insertRef("ParentTree", doc->emit(parentTree));
415
416 // Build the IDTree, a mapping from every unique ID string to
417 // a reference to its corresponding structure element node.
418 if (!fIdTreeEntries.empty()) {
419 std::sort(fIdTreeEntries.begin(), fIdTreeEntries.end(),
420 [](const IDTreeEntry& a, const IDTreeEntry& b) {
421 return a.nodeId < b.nodeId;
422 });
423
424 SkPDFDict idTree;
425 SkPDFDict idTreeLeaf;
426 auto limits = SkPDFMakeArray();
427 SkString lowestNodeIdString = SkPDFTagNode::nodeIdToString(
428 fIdTreeEntries.begin()->nodeId);
429 limits->appendByteString(lowestNodeIdString);
430 SkString highestNodeIdString = SkPDFTagNode::nodeIdToString(
431 fIdTreeEntries.rbegin()->nodeId);
432 limits->appendByteString(highestNodeIdString);
433 idTreeLeaf.insertObject("Limits", std::move(limits));
434 auto names = SkPDFMakeArray();
435 for (const IDTreeEntry& entry : fIdTreeEntries) {
436 SkString idString = SkPDFTagNode::nodeIdToString(entry.nodeId);
437 names->appendByteString(idString);
438 names->appendRef(entry.ref);
439 }
440 idTreeLeaf.insertObject("Names", std::move(names));
441 auto idTreeKids = SkPDFMakeArray();
442 idTreeKids->appendRef(doc->emit(idTreeLeaf));
443 idTree.insertObject("Kids", std::move(idTreeKids));
444 structTreeRoot.insertRef("IDTree", doc->emit(idTree));
445 }
446
447 return doc->emit(structTreeRoot, ref);
448}
static std::vector< SkPDFIndirectReference > sort(const THashSet< SkPDFIndirectReference > &src)
static std::unique_ptr< SkPDFArray > SkPDFMakeArray(Args... args)
Definition: SkPDFTypes.h:125
constexpr int SkToInt(S x)
Definition: SkTo.h:29
void appendRef(SkPDFIndirectReference)
Definition: SkPDFTypes.cpp:442
void insertObject(const char key[], std::unique_ptr< SkPDFObject > &&)
Definition: SkPDFTypes.cpp:484
static bool b
struct MyStruct a[10]
static void mark(SkCanvas *canvas, SkScalar x, SkScalar y, Fn &&fn)
Definition: gm.cpp:211
static const char *const names[]
Definition: symbols.cc:24
SkPDFIndirectReference fRef
Definition: SkPDFTag.cpp:85
static SkString nodeIdToString(int nodeId)
Definition: SkPDFTag.cpp:66

The documentation for this class was generated from the following files: