mirror of
https://github.com/mozilla/pdf.js.git
synced 2026-08-03 04:47:21 +02:00
Compare commits
No commits in common. "1cb14a02d33d62527da79d625870ec550aaecc8b" and "e6cb600896f488c8cef1cfe291d097f91bd67fd1" have entirely different histories.
1cb14a02d3
...
e6cb600896
1168
package-lock.json
generated
1168
package-lock.json
generated
File diff suppressed because it is too large
Load Diff
14
package.json
14
package.json
@ -11,15 +11,15 @@
|
|||||||
"@metalsmith/layouts": "^3.0.0",
|
"@metalsmith/layouts": "^3.0.0",
|
||||||
"@metalsmith/markdown": "^1.10.0",
|
"@metalsmith/markdown": "^1.10.0",
|
||||||
"@napi-rs/canvas": "^1.0.0",
|
"@napi-rs/canvas": "^1.0.0",
|
||||||
"@types/node": "^25.9.1",
|
"@types/node": "^25.6.2",
|
||||||
"autoprefixer": "^10.5.0",
|
"autoprefixer": "^10.5.0",
|
||||||
"babel-loader": "^10.1.1",
|
"babel-loader": "^10.1.1",
|
||||||
"babel-plugin-add-header-comment": "^1.0.3",
|
"babel-plugin-add-header-comment": "^1.0.3",
|
||||||
"babel-plugin-istanbul": "^8.0.0",
|
"babel-plugin-istanbul": "^8.0.0",
|
||||||
"cached-iterable": "^0.3.0",
|
"cached-iterable": "^0.3.0",
|
||||||
"caniuse-lite": "^1.0.30001793",
|
"caniuse-lite": "^1.0.30001792",
|
||||||
"core-js": "^3.49.0",
|
"core-js": "^3.49.0",
|
||||||
"eslint": "^10.4.0",
|
"eslint": "^10.3.0",
|
||||||
"eslint-config-prettier": "^10.1.8",
|
"eslint-config-prettier": "^10.1.8",
|
||||||
"eslint-plugin-import-x": "^4.16.2",
|
"eslint-plugin-import-x": "^4.16.2",
|
||||||
"eslint-plugin-jasmine": "^4.2.2",
|
"eslint-plugin-jasmine": "^4.2.2",
|
||||||
@ -46,12 +46,12 @@
|
|||||||
"metalsmith-html-relative": "^2.0.12",
|
"metalsmith-html-relative": "^2.0.12",
|
||||||
"ordered-read-streams": "^2.0.0",
|
"ordered-read-streams": "^2.0.0",
|
||||||
"pngjs": "^7.0.0",
|
"pngjs": "^7.0.0",
|
||||||
"postcss": "^8.5.15",
|
"postcss": "^8.5.14",
|
||||||
"postcss-discard-comments": "^8.0.0",
|
"postcss-discard-comments": "^8.0.0",
|
||||||
"postcss-values-parser": "^8.0.0",
|
"postcss-values-parser": "^7.0.0",
|
||||||
"prettier": "^3.8.3",
|
"prettier": "^3.8.3",
|
||||||
"puppeteer": "^24.43.1",
|
"puppeteer": "^24.43.1",
|
||||||
"stylelint": "^17.12.0",
|
"stylelint": "^17.11.0",
|
||||||
"stylelint-prettier": "^5.0.3",
|
"stylelint-prettier": "^5.0.3",
|
||||||
"svglint": "^4.2.1",
|
"svglint": "^4.2.1",
|
||||||
"terser-webpack-plugin": "^5.6.0",
|
"terser-webpack-plugin": "^5.6.0",
|
||||||
@ -59,7 +59,7 @@
|
|||||||
"ttest": "^4.0.0",
|
"ttest": "^4.0.0",
|
||||||
"typescript": "^6.0.3",
|
"typescript": "^6.0.3",
|
||||||
"vinyl": "^3.0.1",
|
"vinyl": "^3.0.1",
|
||||||
"webpack": "^5.107.1",
|
"webpack": "^5.106.2",
|
||||||
"webpack-stream": "^7.0.0"
|
"webpack-stream": "^7.0.0"
|
||||||
},
|
},
|
||||||
"repository": {
|
"repository": {
|
||||||
|
|||||||
@ -17,7 +17,6 @@ import {
|
|||||||
bytesToString,
|
bytesToString,
|
||||||
FormatError,
|
FormatError,
|
||||||
info,
|
info,
|
||||||
isArrayEqual,
|
|
||||||
shadow,
|
shadow,
|
||||||
stringToBytes,
|
stringToBytes,
|
||||||
Util,
|
Util,
|
||||||
@ -34,20 +33,6 @@ import { DataBuilder } from "./data_builder.js";
|
|||||||
// Maximum subroutine call depth of type 2 charstrings. Matches OTS.
|
// Maximum subroutine call depth of type 2 charstrings. Matches OTS.
|
||||||
const MAX_SUBR_NESTING = 10;
|
const MAX_SUBR_NESTING = 10;
|
||||||
|
|
||||||
function looksLikeUnsigned16BitNegative(coord) {
|
|
||||||
return coord > 0x7fff && coord <= 0xffff;
|
|
||||||
}
|
|
||||||
|
|
||||||
function recoverSigned16BitBBox(bbox, onlyLowerLeft = false) {
|
|
||||||
return Util.normalizeRect(
|
|
||||||
bbox.map((coord, i) =>
|
|
||||||
(!onlyLowerLeft || i < 2) && looksLikeUnsigned16BitNegative(coord)
|
|
||||||
? coord - 0x10000
|
|
||||||
: coord
|
|
||||||
)
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* The CFF class takes a Type1 file and wrap it into a
|
* The CFF class takes a Type1 file and wrap it into a
|
||||||
* 'Compact Font Format' which itself embed Type2 charstrings.
|
* 'Compact Font Format' which itself embed Type2 charstrings.
|
||||||
@ -283,36 +268,13 @@ class CFFParser {
|
|||||||
}
|
}
|
||||||
|
|
||||||
let fontBBox = topDict.getByName("FontBBox");
|
let fontBBox = topDict.getByName("FontBBox");
|
||||||
const descriptorBBox = properties.bbox?.some(coord => coord !== 0)
|
if (fontBBox?.every(coord => coord === 0) && properties.bbox) {
|
||||||
? recoverSigned16BitBBox(properties.bbox)
|
fontBBox = Util.normalizeRect(
|
||||||
: null;
|
properties.bbox.map(coord =>
|
||||||
const cffBBoxHasUnsignedLowerLeft = fontBBox
|
coord > 0x7fff && coord <= 0xffff ? coord - 0x10000 : coord
|
||||||
?.slice(0, 2)
|
)
|
||||||
.some(looksLikeUnsigned16BitNegative);
|
|
||||||
const cffBBoxHasUnsignedCoords = fontBBox?.some(
|
|
||||||
looksLikeUnsigned16BitNegative
|
|
||||||
);
|
);
|
||||||
if (fontBBox?.every(coord => coord === 0) && descriptorBBox) {
|
|
||||||
// The CFF FontBBox is empty, hence fall back to the FontDescriptor bbox.
|
|
||||||
fontBBox = descriptorBBox;
|
|
||||||
topDict.setByName("FontBBox", fontBBox);
|
topDict.setByName("FontBBox", fontBBox);
|
||||||
} else if (cffBBoxHasUnsignedCoords) {
|
|
||||||
const recoveredFontBBox = recoverSigned16BitBBox(fontBBox);
|
|
||||||
const descriptorCorroborates =
|
|
||||||
descriptorBBox &&
|
|
||||||
properties.bbox.some(coord => coord < 0) &&
|
|
||||||
!properties.bbox.some(looksLikeUnsigned16BitNegative) &&
|
|
||||||
isArrayEqual(recoveredFontBBox, descriptorBBox);
|
|
||||||
|
|
||||||
if (descriptorCorroborates || cffBBoxHasUnsignedLowerLeft) {
|
|
||||||
// Some Ghostscript-generated CFF fonts encode negative lower-left
|
|
||||||
// coordinates as unsigned 16-bit values. Preserve large upper-right
|
|
||||||
// coordinates unless the descriptor independently confirms the repair.
|
|
||||||
fontBBox = descriptorCorroborates
|
|
||||||
? recoveredFontBBox
|
|
||||||
: recoverSigned16BitBBox(fontBBox, /* onlyLowerLeft = */ true);
|
|
||||||
topDict.setByName("FontBBox", fontBBox);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
if (fontBBox?.some(coord => coord !== 0)) {
|
if (fontBBox?.some(coord => coord !== 0)) {
|
||||||
// adjusting ascent/descent
|
// adjusting ascent/descent
|
||||||
|
|||||||
1
test/pdfs/.gitignore
vendored
1
test/pdfs/.gitignore
vendored
@ -923,4 +923,3 @@
|
|||||||
!issue18032.pdf
|
!issue18032.pdf
|
||||||
!Embedded_font.pdf
|
!Embedded_font.pdf
|
||||||
!issue18548_reduced.pdf
|
!issue18548_reduced.pdf
|
||||||
!issue_cff_unsigned_bbox.pdf
|
|
||||||
|
|||||||
Binary file not shown.
@ -14320,12 +14320,5 @@
|
|||||||
"firstPage": 1,
|
"firstPage": 1,
|
||||||
"lastPage": 1,
|
"lastPage": 1,
|
||||||
"type": "eq"
|
"type": "eq"
|
||||||
},
|
|
||||||
{
|
|
||||||
"id": "issue_cff_unsigned_bbox",
|
|
||||||
"file": "pdfs/issue_cff_unsigned_bbox.pdf",
|
|
||||||
"md5": "d2606e2c6cc9e679b8b88c2800c6e1a9",
|
|
||||||
"rounds": 1,
|
|
||||||
"type": "eq"
|
|
||||||
}
|
}
|
||||||
]
|
]
|
||||||
|
|||||||
@ -154,90 +154,6 @@ describe("CFFParser", function () {
|
|||||||
expect(properties.ascentScaled).toEqual(true);
|
expect(properties.ascentScaled).toEqual(true);
|
||||||
});
|
});
|
||||||
|
|
||||||
it("repairs a FontBBox with unsigned-encoded negative coordinates", function () {
|
|
||||||
// [-456, -305, 2158, 989] encoded as unsigned 16-bit values; produced
|
|
||||||
// by some Ghostscript-generated CFF fonts.
|
|
||||||
cff.topDict.setByName("FontBBox", [65080, 65231, 2158, 989]);
|
|
||||||
const fontDataRepaired = new CFFCompiler(cff).compile();
|
|
||||||
|
|
||||||
const properties = {
|
|
||||||
bbox: [-456, -305, 2158, 989],
|
|
||||||
};
|
|
||||||
const reparsedCff = new CFFParser(
|
|
||||||
new Stream(fontDataRepaired),
|
|
||||||
properties,
|
|
||||||
SEAC_ANALYSIS_ENABLED
|
|
||||||
).parse();
|
|
||||||
|
|
||||||
expect(reparsedCff.topDict.getByName("FontBBox")).toEqual([
|
|
||||||
-456, -305, 2158, 989,
|
|
||||||
]);
|
|
||||||
expect(properties.ascent).toEqual(989);
|
|
||||||
expect(properties.descent).toEqual(-305);
|
|
||||||
expect(properties.ascentScaled).toEqual(true);
|
|
||||||
});
|
|
||||||
|
|
||||||
it("doesn't replace a repairable FontBBox with an empty descriptor bbox", function () {
|
|
||||||
cff.topDict.setByName("FontBBox", [65080, 65231, 2158, 989]);
|
|
||||||
const fontDataRepaired = new CFFCompiler(cff).compile();
|
|
||||||
|
|
||||||
const properties = {
|
|
||||||
bbox: [0, 0, 0, 0],
|
|
||||||
};
|
|
||||||
const reparsedCff = new CFFParser(
|
|
||||||
new Stream(fontDataRepaired),
|
|
||||||
properties,
|
|
||||||
SEAC_ANALYSIS_ENABLED
|
|
||||||
).parse();
|
|
||||||
|
|
||||||
expect(reparsedCff.topDict.getByName("FontBBox")).toEqual([
|
|
||||||
-456, -305, 2158, 989,
|
|
||||||
]);
|
|
||||||
expect(properties.ascent).toEqual(989);
|
|
||||||
expect(properties.descent).toEqual(-305);
|
|
||||||
expect(properties.ascentScaled).toEqual(true);
|
|
||||||
});
|
|
||||||
|
|
||||||
it("repairs unsigned-encoded negative FontBBox without descriptor data", function () {
|
|
||||||
cff.topDict.setByName("FontBBox", [65080, 65231, 2158, 989]);
|
|
||||||
const fontDataRepaired = new CFFCompiler(cff).compile();
|
|
||||||
|
|
||||||
const properties = {};
|
|
||||||
const reparsedCff = new CFFParser(
|
|
||||||
new Stream(fontDataRepaired),
|
|
||||||
properties,
|
|
||||||
SEAC_ANALYSIS_ENABLED
|
|
||||||
).parse();
|
|
||||||
|
|
||||||
expect(reparsedCff.topDict.getByName("FontBBox")).toEqual([
|
|
||||||
-456, -305, 2158, 989,
|
|
||||||
]);
|
|
||||||
expect(properties.ascent).toEqual(989);
|
|
||||||
expect(properties.descent).toEqual(-305);
|
|
||||||
expect(properties.ascentScaled).toEqual(true);
|
|
||||||
});
|
|
||||||
|
|
||||||
it("preserves large positive upper FontBBox coordinates", function () {
|
|
||||||
cff.topDict.setByName("FontBBox", [0, -305, 40000, 989]);
|
|
||||||
const fontDataRepaired = new CFFCompiler(cff).compile();
|
|
||||||
|
|
||||||
const properties = {
|
|
||||||
bbox: [0, -305, 40000, 989],
|
|
||||||
};
|
|
||||||
const reparsedCff = new CFFParser(
|
|
||||||
new Stream(fontDataRepaired),
|
|
||||||
properties,
|
|
||||||
SEAC_ANALYSIS_ENABLED
|
|
||||||
).parse();
|
|
||||||
|
|
||||||
expect(reparsedCff.topDict.getByName("FontBBox")).toEqual([
|
|
||||||
0, -305, 40000, 989,
|
|
||||||
]);
|
|
||||||
expect(properties.ascent).toEqual(989);
|
|
||||||
expect(properties.descent).toEqual(-305);
|
|
||||||
expect(properties.ascentScaled).toEqual(true);
|
|
||||||
});
|
|
||||||
|
|
||||||
it("repairs likely Ghostscript-zeroed FDArray private defaults", function () {
|
it("repairs likely Ghostscript-zeroed FDArray private defaults", function () {
|
||||||
cff.isCIDFont = true;
|
cff.isCIDFont = true;
|
||||||
cff.topDict.setByName("ROS", [0, 0, 0]);
|
cff.topDict.setByName("ROS", [0, 0, 0]);
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user