37 unsigned fPageIndex{0};
39 void accumulate(Location
const& child) {
40 if (!child.fPoint.isFinite()) {
43 if (!fPoint.isFinite()) {
47 if (child.fPageIndex < fPageIndex) {
51 if (child.fPageIndex == fPageIndex) {
52 fPoint.fX =
std::min(child.fPoint.fX, fPoint.fX);
53 fPoint.fY =
std::max(child.fPoint.fY, fPoint.fY);
68 idString.
printf(
"node%08d", nodeId);
104 const char* owner,
const char*
name,
int value) {
108 attrDict->insertName(
"O", owner);
110 fAttrs->appendObject(std::move(attrDict));
114 const char* owner,
const char*
name,
float value) {
118 attrDict->insertName(
"O", owner);
120 fAttrs->appendObject(std::move(attrDict));
124 const char* owner,
const char*
name,
const char*
value) {
128 attrDict->insertName(
"O", owner);
130 fAttrs->appendObject(std::move(attrDict));
134 const char* owner,
const char*
name,
const std::vector<float>&
value) {
138 attrDict->insertName(
"O", owner);
140 for (
float element :
value) {
141 pdfArray->appendScalar(element);
143 attrDict->insertObject(
name, std::move(pdfArray));
144 fAttrs->appendObject(std::move(attrDict));
150 const std::vector<int>& nodeIds) {
154 attrDict->insertName(
"O", owner);
156 for (
int nodeId : nodeIds) {
158 pdfArray->appendByteString(idString);
160 attrDict->insertObject(
name, std::move(pdfArray));
161 fAttrs->appendObject(std::move(attrDict));
177 nodeMap->
set(nodeId,
dst);
185 dst->fWantTitle = wantTitle;
193 dst->fChildCount = childCount;
194 dst->fChildren = children;
195 for (
size_t i = 0;
i < childCount; ++
i) {
196 Copy(*node.
fChildVector[
i], &children[
i], arena, nodeMap, wantTitle);
206 Copy(*node, fRoot, &fArena, &fNodeMap,
false);
215 return fNode->fMarkedContent[fMarkIndex].fLocation.fPoint;
228 while (
SkToUInt(fMarksPerPage.
size()) < pageIndex + 1) {
232 int markId = pageMarks.
size();
252 static_cast<int>(fParentTreeAnnotationNodeIds.size());
253 fParentTreeAnnotationNodeIds.push_back(nodeId);
254 return nextStructParentKey;
285 for (
size_t i = 0;
i < childCount; ++
i) {
288 kids->appendRef(PrepareTagTreeToEmit(ref, child, doc));
293 mcr->insertRef(
"Pg", doc->
getPage(
info.fLocation.fPageIndex));
294 mcr->insertInt(
"MCID",
info.fMarkId);
295 kids->appendObject(std::move(mcr));
298 std::unique_ptr<SkPDFDict> annotationDict =
SkPDFMakeDict(
"OBJR");
301 kids->appendObject(std::move(annotationDict));
307 dict.insertTextString(
"Alt", node->
fAlt);
310 dict.insertTextString(
"Lang", node->
fLang);
312 dict.insertRef(
"P", parent);
313 dict.insertObject(
"K", std::move(kids));
315 dict.insertObject(
"A", std::move(node->
fAttributes));
322 dict.insertByteString(
"ID", idString.
c_str());
323 IDTreeEntry idTreeEntry = {node->
fNodeId, ref};
324 fIdTreeEntries.push_back(idTreeEntry);
326 return doc->
emit(dict, ref);
374 SkPDFDict structTreeRoot(
"StructTreeRoot");
375 structTreeRoot.
insertRef(
"K", PrepareTagTreeToEmit(ref, fRoot, doc));
388 for (
int j = 0; j < fMarksPerPage.
size(); ++j) {
395 parentTreeNums->appendInt(j);
396 parentTreeNums->appendRef(doc->
emit(markToTagArray));
400 for (
size_t j = 0; j < fParentTreeAnnotationNodeIds.size(); ++j) {
401 int nodeId = fParentTreeAnnotationNodeIds[j];
409 parentTreeNums->appendInt(structParentKey);
410 parentTreeNums->appendRef(tag->
fRef);
413 parentTree.
insertObject(
"Nums", std::move(parentTreeNums));
414 structTreeRoot.
insertRef(
"ParentTree", doc->
emit(parentTree));
418 if (!fIdTreeEntries.empty()) {
419 std::sort(fIdTreeEntries.begin(), fIdTreeEntries.end(),
420 [](
const IDTreeEntry&
a,
const IDTreeEntry&
b) {
421 return a.nodeId < b.nodeId;
428 fIdTreeEntries.begin()->nodeId);
429 limits->appendByteString(lowestNodeIdString);
431 fIdTreeEntries.rbegin()->nodeId);
432 limits->appendByteString(highestNodeIdString);
435 for (
const IDTreeEntry& entry : fIdTreeEntries) {
437 names->appendByteString(idString);
438 names->appendRef(entry.ref);
442 idTreeKids->appendRef(doc->
emit(idTreeLeaf));
447 return doc->
emit(structTreeRoot, ref);
455 void accumulate(Content
const& child) {
456 fText += child.fText;
457 fLocation.accumulate(child.fLocation);
465 std::vector<OutlineEntry> fChildren = {};
466 size_t fDescendentsEmitted = 0;
469 fDescendentsEmitted = fChildren.size();
470 for (
size_t i = 0;
i < fChildren.size(); ++
i) {
471 auto&& child = fChildren[
i];
472 child.emitDescendents(doc);
473 fDescendentsEmitted += child.fDescendentsEmitted;
479 destination->appendRef(doc->
getPage(child.fContent.fLocation.fPageIndex));
480 destination->appendName(
"XYZ");
481 destination->appendScalar(child.fContent.fLocation.fPoint.x());
482 destination->appendScalar(child.fContent.fLocation.fPoint.y());
483 destination->appendInt(0);
487 if (child.fStructureRef) {
488 entry.
insertRef(
"SE", child.fStructureRef);
493 if (
i < fChildren.size()-1) {
499 entry.
insertInt(
"Count", child.fDescendentsEmitted);
506OutlineEntry::Content create_outline_entry_content(
SkPDFTagNode*
const node) {
517 markPoint.accumulate(
mark.fLocation);
520 OutlineEntry::Content
content{std::move(
text), std::move(markPoint)};
524 for (
auto&& child : children) {
528 content.accumulate(create_outline_entry_content(&child));
535 if (
type[0] ==
'H' &&
'1' <=
type[1] &&
type[1] <=
'6') {
537 while (
level <= stack.
back()->fHeaderLevel) {
540 OutlineEntry::Content
content = create_outline_entry_content(node);
541 if (!
content.fText.isEmpty()) {
543 stack.
push_back(&stack.
back()->fChildren.emplace_back(std::move(
e)));
549 for (
auto&& child : children) {
553 create_outline_from_headers(doc, &child, stack);
567 OutlineEntry top{{
SkString(), Location()}, 0, {}, {}};
569 create_outline_from_headers(doc, fRoot, stack);
570 if (top.fChildren.empty()) {
573 top.emitDescendents(doc);
576 outline.
insertRef(
"First", top.fChildren.front().fRef);
577 outline.
insertRef(
"Last", top.fChildren.back().fRef);
578 outline.
insertInt(
"Count", top.fDescendentsEmitted);
580 return doc->
emit(outline, outlineRef);
static void info(const char *fmt,...) SK_PRINTF_LIKE(1
static std::vector< SkPDFIndirectReference > sort(const THashSet< SkPDFIndirectReference > &src)
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)
static float max(float r, float g, float b)
static float min(float r, float g, float b)
union flutter::testing::@2836::KeyboardChange::@76 content
static const char *const names[]
DEF_SWITCHES_START aot vmservice shared library name
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
std::vector< int > fAdditionalNodeIds
AttributeList fAttributes