Skip to content

Commit

Permalink
Ignore color-operators in Type3 glyphs beginning with a d1 operator…
Browse files Browse the repository at this point in the history
… (issue 12705)

Please refer to the PDF specification at https://www.adobe.com/content/dam/acom/en/devnet/acrobat/pdfs/PDF32000_2008.pdf#G8.1977497 and https://www.adobe.com/content/dam/acom/en/devnet/acrobat/pdfs/PDF32000_2008.pdf#G7.3998470

This patch removes the color-operators in the evaluator, since that should be more efficient than doing it repeatedly in the main-thread when rendering the Type3 glyphs.
  • Loading branch information
Snuffleupagus committed Dec 11, 2020
1 parent 00b4f86 commit 67e5db7
Show file tree
Hide file tree
Showing 4 changed files with 81 additions and 3 deletions.
75 changes: 73 additions & 2 deletions src/core/evaluator.js
Original file line number Diff line number Diff line change
Expand Up @@ -3602,7 +3602,7 @@ class TranslatedFont {
var charProcOperatorList = Object.create(null);

for (const key of charProcs.getKeys()) {
loadCharProcsPromise = loadCharProcsPromise.then(function () {
loadCharProcsPromise = loadCharProcsPromise.then(() => {
var glyphStream = charProcs.get(key);
var operatorList = new OperatorList();
return type3Evaluator
Expand All @@ -3612,7 +3612,16 @@ class TranslatedFont {
resources: fontResources,
operatorList,
})
.then(function () {
.then(() => {
// According to the PDF specification, section "9.6.5 Type 3 Fonts"
// and "Table 113":
// "A glyph description that begins with the d1 operator should
// not execute any operators that set the colour (or other
// colour-related parameters) in the graphics state;
// any use of such operators shall be ignored."
if (operatorList.fnArray[0] === OPS.setCharWidthAndBounds) {
this._removeType3ColorOperators(operatorList);
}
charProcOperatorList[key] = operatorList.getIR();

for (const dependency of operatorList.dependencies) {
Expand All @@ -3631,6 +3640,68 @@ class TranslatedFont {
});
return this.type3Loaded;
}

/**
* @private
*/
_removeType3ColorOperators(operatorList) {
if (
typeof PDFJSDev === "undefined" ||
PDFJSDev.test("!PRODUCTION || TESTING")
) {
assert(
operatorList.fnArray[0] === OPS.setCharWidthAndBounds,
"Type3 glyph shall start with the d1 operator."
);
}
let i = 1,
ii = operatorList.length;
while (i < ii) {
switch (operatorList.fnArray[i]) {
case OPS.setStrokeColorSpace:
case OPS.setFillColorSpace:
case OPS.setStrokeColor:
case OPS.setStrokeColorN:
case OPS.setFillColor:
case OPS.setFillColorN:
case OPS.setStrokeGray:
case OPS.setFillGray:
case OPS.setStrokeRGBColor:
case OPS.setFillRGBColor:
case OPS.setStrokeCMYKColor:
case OPS.setFillCMYKColor:
case OPS.shadingFill:
case OPS.setRenderingIntent:
operatorList.fnArray.splice(i, 1);
operatorList.argsArray.splice(i, 1);
ii--;
continue;

case OPS.setGState:
const gStateObj = operatorList.argsArray[i];
let j = 0,
jj = gStateObj.length;
while (j < jj) {
const [gStateKey] = gStateObj[j];
switch (gStateKey) {
case "TR":
case "TR2":
case "HT":
case "BG":
case "BG2":
case "UCR":
case "UCR2":
gStateObj.splice(j, 1);
jj--;
continue;
}
j++;
}
break;
}
i++;
}
}
}

class StateManager {
Expand Down
1 change: 1 addition & 0 deletions test/pdfs/.gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -222,6 +222,7 @@
!issue5734.pdf
!issue4875.pdf
!issue11740_reduced.pdf
!issue12705.pdf
!issue4881.pdf
!issue5994.pdf
!issue6151.pdf
Expand Down
Binary file added test/pdfs/issue12705.pdf
Binary file not shown.
8 changes: 7 additions & 1 deletion test/test_manifest.json
Original file line number Diff line number Diff line change
Expand Up @@ -4531,6 +4531,12 @@
"annotations": true,
"type": "eq"
},
{ "id": "issue12705",
"file": "pdfs/issue12705.pdf",
"md5": "d8725b9dcfef72fd4fa4a39cab711624",
"rounds": 1,
"type": "eq"
},
{ "id": "annotation-strikeout",
"file": "pdfs/annotation-strikeout.pdf",
"md5": "6624e6b5bedd2f2855b6ab12bbf93c57",
Expand Down Expand Up @@ -4894,5 +4900,5 @@
"rounds": 1,
"type": "eq",
"annotations": true
}
}
]

0 comments on commit 67e5db7

Please sign in to comment.