mirror of
https://github.com/foliojs/pdfkit.git
synced 2026-02-01 16:56:57 +00:00
178 lines
4.8 KiB
JavaScript
178 lines
4.8 KiB
JavaScript
/*
|
|
Markings mixin - support marked content sequences in content streams
|
|
By Ben Schmidt
|
|
*/
|
|
|
|
import PDFStructureElement from "../structure_element";
|
|
import PDFStructureContent from "../structure_content";
|
|
import PDFNumberTree from "../number_tree";
|
|
import PDFObject from "../object";
|
|
|
|
export default {
|
|
|
|
initMarkings(options) {
|
|
this.structChildren = [];
|
|
|
|
if (options.tagged) {
|
|
this.getMarkInfoDictionary().data.Marked = true;
|
|
this.getStructTreeRoot();
|
|
}
|
|
},
|
|
|
|
markContent(tag, options = null) {
|
|
if (tag === 'Artifact' || (options && options.mcid)) {
|
|
let toClose = 0;
|
|
this.page.markings.forEach((marking) => {
|
|
if (toClose || marking.structContent || marking.tag === 'Artifact') {
|
|
toClose++;
|
|
}
|
|
});
|
|
while (toClose--) {
|
|
this.endMarkedContent();
|
|
}
|
|
}
|
|
|
|
if (!options) {
|
|
this.page.markings.push({ tag });
|
|
this.addContent(`/${tag} BMC`);
|
|
return this;
|
|
}
|
|
|
|
this.page.markings.push({ tag, options });
|
|
|
|
const dictionary = {};
|
|
|
|
if (typeof options.mcid !== 'undefined') {
|
|
dictionary.MCID = options.mcid;
|
|
}
|
|
if (tag === 'Artifact') {
|
|
if (typeof options.type === 'string') {
|
|
dictionary.Type = options.type;
|
|
}
|
|
if (Array.isArray(options.bbox)) {
|
|
dictionary.BBox = [options.bbox[0], this.page.height - options.bbox[3],
|
|
options.bbox[2], this.page.height - options.bbox[1]];
|
|
}
|
|
if (Array.isArray(options.attached) &&
|
|
options.attached.every(val => typeof val === 'string')) {
|
|
dictionary.Attached = options.attached;
|
|
}
|
|
}
|
|
if (tag === 'Span') {
|
|
if (options.lang) {
|
|
dictionary.Lang = new String(options.lang);
|
|
}
|
|
if (options.alt) {
|
|
dictionary.Alt = new String(options.alt);
|
|
}
|
|
if (options.expanded) {
|
|
dictionary.E = new String(options.expanded);
|
|
}
|
|
if (options.actual) {
|
|
dictionary.ActualText = new String(options.actual);
|
|
}
|
|
}
|
|
|
|
this.addContent(`/${tag} ${PDFObject.convert(dictionary)} BDC`);
|
|
return this;
|
|
},
|
|
|
|
markStructureContent(tag, options = {}) {
|
|
const pageStructParents = this.getStructParentTree().get(this.page.structParentTreeKey);
|
|
const mcid = pageStructParents.length;
|
|
pageStructParents.push(null);
|
|
|
|
this.markContent(tag, { ...options, mcid });
|
|
|
|
const structContent = new PDFStructureContent(this.page.dictionary, mcid);
|
|
this.page.markings.slice(-1)[0].structContent = structContent;
|
|
return structContent;
|
|
},
|
|
|
|
endMarkedContent() {
|
|
this.page.markings.pop();
|
|
this.addContent('EMC');
|
|
return this;
|
|
},
|
|
|
|
struct(type, options = {}, children = null) {
|
|
return new PDFStructureElement(this, type, options, children);
|
|
},
|
|
|
|
addStructure(structElem) {
|
|
const structTreeRoot = this.getStructTreeRoot();
|
|
structElem.setParent(structTreeRoot);
|
|
structElem.setAttached();
|
|
this.structChildren.push(structElem);
|
|
if (!structTreeRoot.data.K) {
|
|
structTreeRoot.data.K = [];
|
|
}
|
|
structTreeRoot.data.K.push(structElem.dictionary);
|
|
return this;
|
|
},
|
|
|
|
initPageMarkings(pageMarkings) {
|
|
pageMarkings.forEach((marking) => {
|
|
if (marking.structContent) {
|
|
const structContent = marking.structContent;
|
|
const newStructContent = this.markStructureContent(marking.tag, marking.options);
|
|
structContent.push(newStructContent);
|
|
this.page.markings.slice(-1)[0].structContent = structContent;
|
|
} else {
|
|
this.markContent(marking.tag, marking.options);
|
|
}
|
|
});
|
|
},
|
|
|
|
endPageMarkings(page) {
|
|
const pageMarkings = page.markings;
|
|
pageMarkings.forEach(() => page.write('EMC'));
|
|
page.markings = [];
|
|
return pageMarkings;
|
|
},
|
|
|
|
getMarkInfoDictionary() {
|
|
if (!this._root.data.MarkInfo) {
|
|
this._root.data.MarkInfo = this.ref({});
|
|
}
|
|
return this._root.data.MarkInfo;
|
|
},
|
|
|
|
getStructTreeRoot() {
|
|
if (!this._root.data.StructTreeRoot) {
|
|
this._root.data.StructTreeRoot = this.ref({
|
|
Type: 'StructTreeRoot',
|
|
ParentTree: new PDFNumberTree(),
|
|
ParentTreeNextKey: 0
|
|
});
|
|
}
|
|
return this._root.data.StructTreeRoot;
|
|
},
|
|
|
|
getStructParentTree() {
|
|
return this.getStructTreeRoot().data.ParentTree;
|
|
},
|
|
|
|
createStructParentTreeNextKey() {
|
|
// initialise the MarkInfo dictionary
|
|
this.getMarkInfoDictionary();
|
|
|
|
const structTreeRoot = this.getStructTreeRoot();
|
|
const key = structTreeRoot.data.ParentTreeNextKey++;
|
|
structTreeRoot.data.ParentTree.add(key, []);
|
|
return key;
|
|
},
|
|
|
|
endMarkings() {
|
|
const structTreeRoot = this._root.data.StructTreeRoot;
|
|
if (structTreeRoot) {
|
|
structTreeRoot.end();
|
|
this.structChildren.forEach((structElem) => structElem.end());
|
|
}
|
|
if (this._root.data.MarkInfo) {
|
|
this._root.data.MarkInfo.end();
|
|
}
|
|
}
|
|
|
|
};
|