Skip to content

Commit 95170ae

Browse files
committed
Add (basic) support for Optional Content in Annotations
Given that Annotations can also have an `OC`-entry, we keep to take that into account when generating their operatorLists. Note that in order to simplify the patch the `getOperatorList`-methods, for the Annotation-classes, were converted to be `async`.
1 parent 3fab4af commit 95170ae

File tree

2 files changed

+132
-74
lines changed

2 files changed

+132
-74
lines changed

src/core/annotation.js

+122-74
Original file line numberDiff line numberDiff line change
@@ -447,6 +447,7 @@ class Annotation {
447447
this.setColor(dict.getArray("C"));
448448
this.setBorderStyle(dict);
449449
this.setAppearance(dict);
450+
this.setOptionalContent(dict);
450451

451452
const MK = dict.get("MK");
452453
this.setBorderAndBackgroundColors(MK);
@@ -842,6 +843,17 @@ class Annotation {
842843
this.appearance = normalAppearanceState.get(as.name);
843844
}
844845

846+
setOptionalContent(dict) {
847+
this.oc = null;
848+
849+
const oc = dict.get("OC");
850+
if (oc instanceof Name) {
851+
warn("setOptionalContent: Support for /Name-entry is not implemented.");
852+
} else if (oc instanceof Dict) {
853+
this.oc = oc;
854+
}
855+
}
856+
845857
loadResources(keys, appearance) {
846858
return appearance.dict.getAsync("Resources").then(resources => {
847859
if (!resources) {
@@ -855,52 +867,69 @@ class Annotation {
855867
});
856868
}
857869

858-
getOperatorList(evaluator, task, intent, renderForms, annotationStorage) {
870+
async getOperatorList(
871+
evaluator,
872+
task,
873+
intent,
874+
renderForms,
875+
annotationStorage
876+
) {
859877
const data = this.data;
860878
let appearance = this.appearance;
861879
const isUsingOwnCanvas =
862880
this.data.hasOwnCanvas && intent & RenderingIntentFlag.DISPLAY;
863881
if (!appearance) {
864882
if (!isUsingOwnCanvas) {
865-
return Promise.resolve(new OperatorList());
883+
return new OperatorList();
866884
}
867885
appearance = new StringStream("");
868886
appearance.dict = new Dict();
869887
}
870888

871889
const appearanceDict = appearance.dict;
872-
const resourcesPromise = this.loadResources(
890+
const resources = await this.loadResources(
873891
["ExtGState", "ColorSpace", "Pattern", "Shading", "XObject", "Font"],
874892
appearance
875893
);
876894
const bbox = appearanceDict.getArray("BBox") || [0, 0, 1, 1];
877895
const matrix = appearanceDict.getArray("Matrix") || [1, 0, 0, 1, 0, 0];
878896
const transform = getTransformMatrix(data.rect, bbox, matrix);
879897

880-
return resourcesPromise.then(resources => {
881-
const opList = new OperatorList();
882-
opList.addOp(OPS.beginAnnotation, [
883-
data.id,
884-
data.rect,
885-
transform,
886-
matrix,
887-
isUsingOwnCanvas,
888-
]);
898+
const opList = new OperatorList();
889899

890-
return evaluator
891-
.getOperatorList({
892-
stream: appearance,
893-
task,
894-
resources,
895-
operatorList: opList,
896-
fallbackFontDict: this._fallbackFontDict,
897-
})
898-
.then(() => {
899-
opList.addOp(OPS.endAnnotation, []);
900-
this.reset();
901-
return opList;
902-
});
900+
let optionalContent;
901+
if (this.oc) {
902+
optionalContent = await evaluator.parseMarkedContentProps(
903+
this.oc,
904+
/* resources = */ null
905+
);
906+
}
907+
if (optionalContent !== undefined) {
908+
opList.addOp(OPS.beginMarkedContentProps, ["OC", optionalContent]);
909+
}
910+
911+
opList.addOp(OPS.beginAnnotation, [
912+
data.id,
913+
data.rect,
914+
transform,
915+
matrix,
916+
isUsingOwnCanvas,
917+
]);
918+
919+
await evaluator.getOperatorList({
920+
stream: appearance,
921+
task,
922+
resources,
923+
operatorList: opList,
924+
fallbackFontDict: this._fallbackFontDict,
903925
});
926+
opList.addOp(OPS.endAnnotation, []);
927+
928+
if (optionalContent !== undefined) {
929+
opList.addOp(OPS.endMarkedContent, []);
930+
}
931+
this.reset();
932+
return opList;
904933
}
905934

906935
async save(evaluator, task, annotationStorage) {
@@ -1575,11 +1604,17 @@ class WidgetAnnotation extends Annotation {
15751604
return str;
15761605
}
15771606

1578-
getOperatorList(evaluator, task, intent, renderForms, annotationStorage) {
1607+
async getOperatorList(
1608+
evaluator,
1609+
task,
1610+
intent,
1611+
renderForms,
1612+
annotationStorage
1613+
) {
15791614
// Do not render form elements on the canvas when interactive forms are
15801615
// enabled. The display layer is responsible for rendering them instead.
15811616
if (renderForms && !(this instanceof SignatureWidgetAnnotation)) {
1582-
return Promise.resolve(new OperatorList());
1617+
return new OperatorList();
15831618
}
15841619

15851620
if (!this._hasText) {
@@ -1592,56 +1627,69 @@ class WidgetAnnotation extends Annotation {
15921627
);
15931628
}
15941629

1595-
return this._getAppearance(evaluator, task, annotationStorage).then(
1596-
content => {
1597-
if (this.appearance && content === null) {
1598-
return super.getOperatorList(
1599-
evaluator,
1600-
task,
1601-
intent,
1602-
renderForms,
1603-
annotationStorage
1604-
);
1605-
}
1630+
const content = await this._getAppearance(
1631+
evaluator,
1632+
task,
1633+
annotationStorage
1634+
);
1635+
if (this.appearance && content === null) {
1636+
return super.getOperatorList(
1637+
evaluator,
1638+
task,
1639+
intent,
1640+
renderForms,
1641+
annotationStorage
1642+
);
1643+
}
16061644

1607-
const operatorList = new OperatorList();
1645+
const operatorList = new OperatorList();
16081646

1609-
// Even if there is an appearance stream, ignore it. This is the
1610-
// behaviour used by Adobe Reader.
1611-
if (!this._defaultAppearance || content === null) {
1612-
return operatorList;
1613-
}
1647+
// Even if there is an appearance stream, ignore it. This is the
1648+
// behaviour used by Adobe Reader.
1649+
if (!this._defaultAppearance || content === null) {
1650+
return operatorList;
1651+
}
16141652

1615-
const matrix = [1, 0, 0, 1, 0, 0];
1616-
const bbox = [
1617-
0,
1618-
0,
1619-
this.data.rect[2] - this.data.rect[0],
1620-
this.data.rect[3] - this.data.rect[1],
1621-
];
1622-
1623-
const transform = getTransformMatrix(this.data.rect, bbox, matrix);
1624-
operatorList.addOp(OPS.beginAnnotation, [
1625-
this.data.id,
1626-
this.data.rect,
1627-
transform,
1628-
this.getRotationMatrix(annotationStorage),
1629-
]);
1630-
1631-
const stream = new StringStream(content);
1632-
return evaluator
1633-
.getOperatorList({
1634-
stream,
1635-
task,
1636-
resources: this._fieldResources.mergedResources,
1637-
operatorList,
1638-
})
1639-
.then(function () {
1640-
operatorList.addOp(OPS.endAnnotation, []);
1641-
return operatorList;
1642-
});
1643-
}
1644-
);
1653+
const matrix = [1, 0, 0, 1, 0, 0];
1654+
const bbox = [
1655+
0,
1656+
0,
1657+
this.data.rect[2] - this.data.rect[0],
1658+
this.data.rect[3] - this.data.rect[1],
1659+
];
1660+
const transform = getTransformMatrix(this.data.rect, bbox, matrix);
1661+
1662+
let optionalContent;
1663+
if (this.oc) {
1664+
optionalContent = await evaluator.parseMarkedContentProps(
1665+
this.oc,
1666+
/* resources = */ null
1667+
);
1668+
}
1669+
if (optionalContent !== undefined) {
1670+
operatorList.addOp(OPS.beginMarkedContentProps, ["OC", optionalContent]);
1671+
}
1672+
1673+
operatorList.addOp(OPS.beginAnnotation, [
1674+
this.data.id,
1675+
this.data.rect,
1676+
transform,
1677+
this.getRotationMatrix(annotationStorage),
1678+
]);
1679+
1680+
const stream = new StringStream(content);
1681+
await evaluator.getOperatorList({
1682+
stream,
1683+
task,
1684+
resources: this._fieldResources.mergedResources,
1685+
operatorList,
1686+
});
1687+
operatorList.addOp(OPS.endAnnotation, []);
1688+
1689+
if (optionalContent !== undefined) {
1690+
operatorList.addOp(OPS.endMarkedContent, []);
1691+
}
1692+
return operatorList;
16451693
}
16461694

16471695
_getMKDict(rotation) {

test/test_manifest.json

+10
Original file line numberDiff line numberDiff line change
@@ -6561,6 +6561,16 @@
65616561
}
65626562
}
65636563
},
6564+
{ "id": "bug1737260-oc",
6565+
"file": "pdfs/bug1737260.pdf",
6566+
"md5": "8bd4f810d30972764b07ae141a4afbc4",
6567+
"rounds": 1,
6568+
"link": true,
6569+
"type": "eq",
6570+
"optionalContent": {
6571+
"191R": false
6572+
}
6573+
},
65646574
{ "id": "bug1737260",
65656575
"file": "pdfs/bug1737260.pdf",
65666576
"md5": "8bd4f810d30972764b07ae141a4afbc4",

0 commit comments

Comments
 (0)