28 unsigned fPageIndex{0};
30 void accumulate(
Location const& child) {
31 if (!child.fPoint.isFinite()) {
34 if (!fPoint.isFinite()) {
38 if (child.fPageIndex < fPageIndex) {
42 if (child.fPageIndex == fPageIndex) {
43 fPoint.fX = std::min(child.fPoint.fX, fPoint.fX);
44 fPoint.fY = std::max(child.fPoint.fY, fPoint.fY);
59 idString.
printf(
"node%08d", nodeId);
95 const char* owner,
const char*
name,
int value) {
99 attrDict->insertName(
"O", owner);
101 fAttrs->appendObject(std::move(attrDict));
105 const char* owner,
const char*
name,
float value) {
109 attrDict->insertName(
"O", owner);
111 fAttrs->appendObject(std::move(attrDict));
115 const char* owner,
const char*
name,
const char* value) {
119 attrDict->insertName(
"O", owner);
121 fAttrs->appendObject(std::move(attrDict));
125 const char* owner,
const char*
name,
const std::vector<float>& value) {
129 attrDict->insertName(
"O", owner);
131 for (
float element :
value) {
132 pdfArray->appendScalar(element);
134 attrDict->insertObject(
name, std::move(pdfArray));
135 fAttrs->appendObject(std::move(attrDict));
141 const std::vector<int>& nodeIds) {
145 attrDict->insertName(
"O", owner);
147 for (
int nodeId : nodeIds) {
149 pdfArray->appendByteString(idString);
151 attrDict->insertObject(
name, std::move(pdfArray));
152 fAttrs->appendObject(std::move(attrDict));
166 for (
int nodeId : node.fAdditionalNodeIds) {
168 nodeMap->
set(nodeId, dst);
176 dst->fWantTitle = wantTitle;
184 dst->fChildCount = childCount;
185 dst->fChildren = children;
186 for (
size_t i = 0; i < childCount; ++i) {
187 Copy(*node.
fChildVector[i], &children[i], arena, nodeMap, wantTitle);
197 Copy(*node, fRoot, &fArena, &fNodeMap,
false);
206 return fNode->fMarkedContent[fMarkIndex].fLocation.fPoint;
219 while (
SkToUInt(fMarksPerPage.
size()) < pageIndex + 1) {
223 int markId = pageMarks.
size();
243 static_cast<int>(fParentTreeAnnotationNodeIds.size());
244 fParentTreeAnnotationNodeIds.push_back(nodeId);
245 return nextStructParentKey;
276 for (
size_t i = 0; i < childCount; ++i) {
279 kids->appendRef(PrepareTagTreeToEmit(ref, child, doc));
284 mcr->insertRef(
"Pg", doc->
getPage(
info.fLocation.fPageIndex));
285 mcr->insertInt(
"MCID",
info.fMarkId);
286 kids->appendObject(std::move(mcr));
289 std::unique_ptr<SkPDFDict> annotationDict =
SkPDFMakeDict(
"OBJR");
290 annotationDict->insertRef(
"Obj", annotationInfo.fAnnotationRef);
291 annotationDict->insertRef(
"Pg", doc->
getPage(annotationInfo.fPageIndex));
292 kids->appendObject(std::move(annotationDict));
298 dict.insertTextString(
"Alt", node->
fAlt);
301 dict.insertTextString(
"Lang", node->
fLang);
303 dict.insertRef(
"P", parent);
304 dict.insertObject(
"K", std::move(kids));
306 dict.insertObject(
"A", std::move(node->
fAttributes));
313 dict.insertByteString(
"ID", idString.
c_str());
314 IDTreeEntry idTreeEntry = {node->
fNodeId, ref};
315 fIdTreeEntries.push_back(idTreeEntry);
317 return doc->
emit(dict, ref);
365 SkPDFDict structTreeRoot(
"StructTreeRoot");
366 structTreeRoot.
insertRef(
"K", PrepareTagTreeToEmit(ref, fRoot, doc));
379 for (
int j = 0; j < fMarksPerPage.
size(); ++j) {
386 parentTreeNums->appendInt(j);
387 parentTreeNums->appendRef(doc->
emit(markToTagArray));
391 for (
size_t j = 0; j < fParentTreeAnnotationNodeIds.size(); ++j) {
392 int nodeId = fParentTreeAnnotationNodeIds[j];
400 parentTreeNums->appendInt(structParentKey);
401 parentTreeNums->appendRef(tag->
fRef);
404 parentTree.
insertObject(
"Nums", std::move(parentTreeNums));
405 structTreeRoot.
insertRef(
"ParentTree", doc->
emit(parentTree));
409 if (!fIdTreeEntries.empty()) {
410 std::sort(fIdTreeEntries.begin(), fIdTreeEntries.end(),
411 [](
const IDTreeEntry&
a,
const IDTreeEntry&
b) {
412 return a.nodeId < b.nodeId;
419 fIdTreeEntries.begin()->nodeId);
420 limits->appendByteString(lowestNodeIdString);
422 fIdTreeEntries.rbegin()->nodeId);
423 limits->appendByteString(highestNodeIdString);
426 for (
const IDTreeEntry& entry : fIdTreeEntries) {
428 names->appendByteString(idString);
429 names->appendRef(entry.ref);
433 idTreeKids->appendRef(doc->
emit(idTreeLeaf));
438 return doc->
emit(structTreeRoot, ref);
446 void accumulate(Content
const& child) {
447 fText += child.fText;
448 fLocation.accumulate(child.fLocation);
456 std::vector<OutlineEntry> fChildren = {};
457 size_t fDescendentsEmitted = 0;
460 fDescendentsEmitted = fChildren.size();
461 for (
size_t i = 0; i < fChildren.size(); ++i) {
462 auto&& child = fChildren[i];
463 child.emitDescendents(doc);
464 fDescendentsEmitted += child.fDescendentsEmitted;
470 destination->appendRef(doc->
getPage(child.fContent.fLocation.fPageIndex));
471 destination->appendName(
"XYZ");
472 destination->appendScalar(child.fContent.fLocation.fPoint.x());
473 destination->appendScalar(child.fContent.fLocation.fPoint.y());
474 destination->appendInt(0);
478 if (child.fStructureRef) {
479 entry.
insertRef(
"SE", child.fStructureRef);
482 entry.
insertRef(
"Prev", fChildren[i-1].fRef);
484 if (i < fChildren.size()-1) {
485 entry.
insertRef(
"Next", fChildren[i+1].fRef);
490 entry.
insertInt(
"Count", child.fDescendentsEmitted);
497OutlineEntry::Content create_outline_entry_content(
SkPDFTagNode*
const node) {
507 for (
auto&&
mark : node->fMarkedContent) {
508 markPoint.accumulate(
mark.fLocation);
511 OutlineEntry::Content
content{std::move(
text), std::move(markPoint)};
515 for (
auto&& child : children) {
519 content.accumulate(create_outline_entry_content(&child));
526 if (
type[0] ==
'H' &&
'1' <=
type[1] &&
type[1] <=
'6') {
528 while (level <= stack.
back()->fHeaderLevel) {
531 OutlineEntry::Content
content = create_outline_entry_content(node);
532 if (!
content.fText.isEmpty()) {
534 stack.
push_back(&stack.
back()->fChildren.emplace_back(std::move(e)));
540 for (
auto&& child : children) {
544 create_outline_from_headers(doc, &child, stack);
558 OutlineEntry top{{
SkString(), Location()}, 0, {}, {}};
560 create_outline_from_headers(doc, fRoot, stack);
561 if (top.fChildren.empty()) {
564 top.emitDescendents(doc);
567 outline.
insertRef(
"First", top.fChildren.front().fRef);
568 outline.
insertRef(
"Last", top.fChildren.back().fRef);
569 outline.
insertInt(
"Count", top.fDescendentsEmitted);
571 return doc->
emit(outline, outlineRef);
static void info(const char *fmt,...) SK_PRINTF_LIKE(1
static bool can_discard(SkPDFTagNode *node)
const int kFirstAnnotationStructParentKey
static std::unique_ptr< SkPDFDict > SkPDFMakeDict(const char *type=nullptr)
static std::unique_ptr< SkPDFArray > SkPDFMakeArray(Args... args)
constexpr int SkToInt(S x)
constexpr unsigned SkToUInt(S x)
T * makeArray(size_t count)
auto make(Ctor &&ctor) -> decltype(ctor(nullptr))
void appendRef(SkPDFIndirectReference)
void insertObject(const char key[], std::unique_ptr< SkPDFObject > &&)
void insertInt(const char key[], int32_t value)
void insertTextString(const char key[], const char value[])
void insertRef(const char key[], SkPDFIndirectReference)
SkPDFIndirectReference emit(const SkPDFObject &, SkPDFIndirectReference)
SkPDFIndirectReference reserveRef()
SkPDFIndirectReference getPage(size_t pageIndex) const
SkPDFIndirectReference makeStructTreeRoot(SkPDFDocument *doc)
int createStructParentKeyForNodeId(int nodeId, unsigned pageIndex)
void init(SkPDF::StructureElementNode *, SkPDF::Metadata::Outline)
SkPDFIndirectReference makeOutline(SkPDFDocument *doc)
void addNodeAnnotation(int nodeId, SkPDFIndirectReference annotationRef, unsigned pageIndex)
SkString getRootLanguage()
Mark createMarkIdForNodeId(int nodeId, unsigned pageIndex, SkPoint)
void addNodeTitle(int nodeId, SkSpan< const char >)
void appendNodeIdArray(const char *owner, const char *attrName, const std::vector< int > &nodeIds)
void appendFloatArray(const char *owner, const char *name, const std::vector< float > &value)
void appendName(const char *owner, const char *attrName, const char *value)
void appendInt(const char *owner, const char *name, int value)
void appendFloat(const char *owner, const char *name, float value)
constexpr T * data() const
constexpr size_t size() const
void printf(const char format[],...) SK_PRINTF_LIKE(2
void append(const char text[])
const char * c_str() const
V * find(const K &key) const
static void mark(SkCanvas *canvas, SkScalar x, SkScalar y, Fn &&fn)
union flutter::testing::@2838::KeyboardChange::@76 content
SkPDFIndirectReference fAnnotationRef
TArray< MarkedContentInfo > fMarkedContent
std::unique_ptr< SkPDFArray > fAttributes
SkPDFIndirectReference fRef
std::vector< AnnotationInfo > fAnnotations
static SkString nodeIdToString(int nodeId)
enum SkPDFTagNode::State fCanDiscard
std::vector< std::unique_ptr< StructureElementNode > > fChildVector
AttributeList fAttributes