mirror of
https://github.com/mozilla/pdf.js.git
synced 2026-10-04 06:18:00 +02:00
Compare commits
23
Commits
c33c32aed4
...
ef62f31f24
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
ef62f31f24 | ||
|
|
c7e2fe4d29 | ||
|
|
8496056b9a | ||
|
|
db561fecc6 | ||
|
|
a00ad131fd | ||
|
|
20b2e11213 | ||
|
|
0f116c95da | ||
|
|
f576c25bcd | ||
|
|
fecddae585 | ||
|
|
637ed4cfe3 | ||
|
|
5baa62329e | ||
|
|
fe0e9afdb1 | ||
|
|
90448db27e | ||
|
|
dc7ac33fcd | ||
|
|
b6753b1bf3 | ||
|
|
1d43a5a956 | ||
|
|
c58ed927af | ||
|
|
05566bd110 | ||
|
|
cf2db3a426 | ||
|
|
f1c5c1513d | ||
|
|
9a6b3808ba | ||
|
|
08526f78df | ||
|
|
f1907720a8 |
@@ -55,7 +55,7 @@ jobs:
|
||||
enableCrossOsArchive: true
|
||||
|
||||
- name: Upload results to Codecov
|
||||
uses: codecov/codecov-action@0b35c9ecc4f0529d0eb674914510c22f85b196b4 # v7.1.0
|
||||
uses: codecov/codecov-action@303a32d7a59b442fa8d48b6a1cc6825c09c847a5 # v7.1.1
|
||||
with:
|
||||
token: ${{ secrets.CODECOV_TOKEN }}
|
||||
fail_ci_if_error: true
|
||||
|
||||
@@ -24,13 +24,13 @@ jobs:
|
||||
persist-credentials: false
|
||||
|
||||
- name: Initialize CodeQL
|
||||
uses: github/codeql-action/init@b96794f015dfd88f77b49b1c93e0fa7110f94c63 # v4.38.0
|
||||
uses: github/codeql-action/init@1c5b675653bb5c22dbe9b12b556ec555138e09fd # v4.38.1
|
||||
with:
|
||||
languages: ${{ matrix.language }}
|
||||
queries: security-and-quality
|
||||
|
||||
- name: Autobuild CodeQL
|
||||
uses: github/codeql-action/autobuild@b96794f015dfd88f77b49b1c93e0fa7110f94c63 # v4.38.0
|
||||
uses: github/codeql-action/autobuild@1c5b675653bb5c22dbe9b12b556ec555138e09fd # v4.38.1
|
||||
|
||||
- name: Perform CodeQL analysis
|
||||
uses: github/codeql-action/analyze@b96794f015dfd88f77b49b1c93e0fa7110f94c63 # v4.38.0
|
||||
uses: github/codeql-action/analyze@1c5b675653bb5c22dbe9b12b556ec555138e09fd # v4.38.1
|
||||
|
||||
@@ -91,7 +91,7 @@ jobs:
|
||||
enableCrossOsArchive: true
|
||||
|
||||
- name: Upload results to Codecov
|
||||
uses: codecov/codecov-action@0b35c9ecc4f0529d0eb674914510c22f85b196b4 # v7.1.0
|
||||
uses: codecov/codecov-action@303a32d7a59b442fa8d48b6a1cc6825c09c847a5 # v7.1.1
|
||||
with:
|
||||
token: ${{ secrets.CODECOV_TOKEN }}
|
||||
fail_ci_if_error: true
|
||||
|
||||
@@ -79,7 +79,7 @@ jobs:
|
||||
run: npx gulp fonttest --headless --coverage --coverage-output build/coverage/font ${{ matrix.skip }}
|
||||
|
||||
- name: Upload results to Codecov
|
||||
uses: codecov/codecov-action@0b35c9ecc4f0529d0eb674914510c22f85b196b4 # v7.1.0
|
||||
uses: codecov/codecov-action@303a32d7a59b442fa8d48b6a1cc6825c09c847a5 # v7.1.1
|
||||
with:
|
||||
token: ${{ secrets.CODECOV_TOKEN }}
|
||||
fail_ci_if_error: true
|
||||
|
||||
@@ -98,7 +98,7 @@ jobs:
|
||||
enableCrossOsArchive: true
|
||||
|
||||
- name: Upload results to Codecov
|
||||
uses: codecov/codecov-action@0b35c9ecc4f0529d0eb674914510c22f85b196b4 # v7.1.0
|
||||
uses: codecov/codecov-action@303a32d7a59b442fa8d48b6a1cc6825c09c847a5 # v7.1.1
|
||||
with:
|
||||
token: ${{ secrets.CODECOV_TOKEN }}
|
||||
fail_ci_if_error: true
|
||||
|
||||
@@ -85,7 +85,7 @@ jobs:
|
||||
enableCrossOsArchive: true
|
||||
|
||||
- name: Upload results to Codecov
|
||||
uses: codecov/codecov-action@0b35c9ecc4f0529d0eb674914510c22f85b196b4 # v7.1.0
|
||||
uses: codecov/codecov-action@303a32d7a59b442fa8d48b6a1cc6825c09c847a5 # v7.1.1
|
||||
with:
|
||||
token: ${{ secrets.CODECOV_TOKEN }}
|
||||
fail_ci_if_error: true
|
||||
|
||||
Generated
+14
-14
@@ -5325,9 +5325,9 @@
|
||||
"license": "ISC"
|
||||
},
|
||||
"node_modules/brace-expansion": {
|
||||
"version": "5.0.9",
|
||||
"resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-5.0.9.tgz",
|
||||
"integrity": "sha512-ScQ4IuvIEF1TMlP7Zt+vjJ//9zlPb2SDcxWxM3bk8s6t6GGdJ7KO1dCcTidOPJKePW30LE/2cT7wCyPho9/Wxg==",
|
||||
"version": "5.0.12",
|
||||
"resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-5.0.12.tgz",
|
||||
"integrity": "sha512-YovQ3rzhaLMIrDjNDMkNS01tea93qhEhG5xy8f6+R0l+dw3Ki+5sCoIoI942iuLZTHWogWktgwVDhU09iNEimQ==",
|
||||
"dev": true,
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
@@ -9141,9 +9141,9 @@
|
||||
}
|
||||
},
|
||||
"node_modules/markdown-it": {
|
||||
"version": "14.2.0",
|
||||
"resolved": "https://registry.npmjs.org/markdown-it/-/markdown-it-14.2.0.tgz",
|
||||
"integrity": "sha512-1TGiQiJVRQ3NPmZH6sx5Cfnmg6GQm9jvC1ch4TK511NjSJvjzKLzn5pPfZRNZkRPZP0HqCioSndqH8v2nRaWVQ==",
|
||||
"version": "14.3.2",
|
||||
"resolved": "https://registry.npmjs.org/markdown-it/-/markdown-it-14.3.2.tgz",
|
||||
"integrity": "sha512-sHHjZ5fJKlgrG4qns2YwVcdNep35h5fERrfkD2YNsb9UFk0UIHarbiTaHKVMlPuWAoiilyK8Fv/jAm11slsY7Q==",
|
||||
"dev": true,
|
||||
"funding": [
|
||||
{
|
||||
@@ -9158,8 +9158,8 @@
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
"argparse": "^2.0.1",
|
||||
"entities": "^4.4.0",
|
||||
"linkify-it": "^5.0.1",
|
||||
"entities": "^4.5.0",
|
||||
"linkify-it": "^5.0.2",
|
||||
"mdurl": "^2.0.0",
|
||||
"punycode.js": "^2.3.1",
|
||||
"uc.micro": "^2.1.0"
|
||||
@@ -11951,9 +11951,9 @@
|
||||
"license": "MIT"
|
||||
},
|
||||
"node_modules/test-exclude/node_modules/brace-expansion": {
|
||||
"version": "2.1.4",
|
||||
"resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-2.1.4.tgz",
|
||||
"integrity": "sha512-hGfVzPxthbf3+2yjg/RBs60cB0FhqBS/zvdV/4wn4/BmN0bNMMHPc4V/BbFieqf1TKAGGAHnY4eSjajCl0f2Xg==",
|
||||
"version": "2.1.7",
|
||||
"resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-2.1.7.tgz",
|
||||
"integrity": "sha512-uZbew1NqdmPDTMJ8ah1y+b+9QEJrfkXFk3RcTQw3X0jW/xRUvFKsg1CfQdSYGdTbXZWExtU3J3ccxtnfw1Fi0g==",
|
||||
"dev": true,
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
@@ -12422,9 +12422,9 @@
|
||||
}
|
||||
},
|
||||
"node_modules/undici": {
|
||||
"version": "7.29.0",
|
||||
"resolved": "https://registry.npmjs.org/undici/-/undici-7.29.0.tgz",
|
||||
"integrity": "sha512-IDxfleLmmbSskfWSUATiN1nfn2rDuvnMOqb5CWR92iIfojA0Ud+ulOAAEQ57LPr9rWmsreUyf5lwyao+7GNNVw==",
|
||||
"version": "7.30.0",
|
||||
"resolved": "https://registry.npmjs.org/undici/-/undici-7.30.0.tgz",
|
||||
"integrity": "sha512-dkrQXeHSaoamnItlYbmzG0wFYrM0ZwDxCIg0A7aKjTyyhh9svRzCNFEzV+Vm05/yehjCzjDZ31KXfGEjYSztDQ==",
|
||||
"dev": true,
|
||||
"license": "MIT",
|
||||
"engines": {
|
||||
|
||||
+1
-12
@@ -96,7 +96,6 @@ const EXPORT_DATA_PROPERTIES = [
|
||||
"isType3Font",
|
||||
"italic",
|
||||
"loadedName",
|
||||
"mimetype",
|
||||
"missingFile",
|
||||
"name",
|
||||
"remeasure",
|
||||
@@ -1050,7 +1049,6 @@ class Font {
|
||||
constructor(name, file, properties, evaluatorOptions) {
|
||||
this.name = name;
|
||||
this.psName = null;
|
||||
this.mimetype = null;
|
||||
this.disableFontFace = evaluatorOptions.disableFontFace;
|
||||
this.fontExtraProperties = evaluatorOptions.fontExtraProperties;
|
||||
|
||||
@@ -1165,8 +1163,6 @@ class Font {
|
||||
/* falls through */
|
||||
case "Type1":
|
||||
case "CIDFontType0":
|
||||
this.mimetype = "font/opentype";
|
||||
|
||||
const cff =
|
||||
subtype === "Type1C" || subtype === "CIDFontType0C"
|
||||
? new CFFFont(file, properties)
|
||||
@@ -1181,8 +1177,6 @@ class Font {
|
||||
case "OpenType":
|
||||
case "TrueType":
|
||||
case "CIDFontType2":
|
||||
this.mimetype = "font/opentype";
|
||||
|
||||
// Repair the TrueType file. It is can be damaged in the point of
|
||||
// view of the sanitizer
|
||||
data = this.checkAndRepair(name, file, properties);
|
||||
@@ -3038,12 +3032,7 @@ class Font {
|
||||
if (cid > 0xffff) {
|
||||
throw new FormatError("Max size of CID is 65,535");
|
||||
}
|
||||
let glyphId = -1;
|
||||
if (isCidToGidMapEmpty) {
|
||||
glyphId = cid;
|
||||
} else if (cidToGidMap.has(cid)) {
|
||||
glyphId = cidToGidMap.get(cid);
|
||||
}
|
||||
const glyphId = isCidToGidMapEmpty ? cid : (cidToGidMap.get(cid) ?? -1);
|
||||
|
||||
if (glyphId >= 0 && glyphId < numGlyphs && hasGlyph(glyphId)) {
|
||||
charCodeToGlyphId.set(charCode, glyphId);
|
||||
|
||||
@@ -423,12 +423,13 @@ class FontFaceObject {
|
||||
}
|
||||
|
||||
createNativeFontFace() {
|
||||
if (!this.data || this.disableFontFace) {
|
||||
const { data } = this; // Get `data` just once, since it's not shadowed.
|
||||
if (!data || this.disableFontFace) {
|
||||
return null;
|
||||
}
|
||||
let nativeFontFace;
|
||||
if (!this.cssFontInfo) {
|
||||
nativeFontFace = new FontFace(this.loadedName, this.data, {});
|
||||
nativeFontFace = new FontFace(this.loadedName, data, {});
|
||||
} else {
|
||||
const css = {
|
||||
weight: this.cssFontInfo.fontWeight,
|
||||
@@ -438,7 +439,7 @@ class FontFaceObject {
|
||||
}
|
||||
nativeFontFace = new FontFace(
|
||||
serializeFontFamily(this.cssFontInfo.fontFamily),
|
||||
this.data,
|
||||
data,
|
||||
css
|
||||
);
|
||||
}
|
||||
@@ -452,11 +453,12 @@ class FontFaceObject {
|
||||
throw new Error("Not implemented: createFontFaceRule");
|
||||
}
|
||||
|
||||
if (!this.data || this.disableFontFace) {
|
||||
const { data } = this; // Get `data` just once, since it's not shadowed.
|
||||
if (!data || this.disableFontFace) {
|
||||
return null;
|
||||
}
|
||||
// Add the @font-face rule to the document.
|
||||
const url = `url(data:${this.mimetype};base64,${this.data.toBase64()});`;
|
||||
const url = `url(data:${this.mimetype};base64,${data.toBase64()});`;
|
||||
let rule;
|
||||
if (!this.cssFontInfo) {
|
||||
rule = `@font-face {font-family:"${this.loadedName}";src:${url}}`;
|
||||
@@ -567,7 +569,7 @@ class FontFaceObject {
|
||||
}
|
||||
|
||||
get mimetype() {
|
||||
return this.#fontData.mimetype;
|
||||
return this.missingFile ? null : "font/opentype";
|
||||
}
|
||||
|
||||
get name() {
|
||||
|
||||
@@ -13,7 +13,13 @@
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
import { assert, BBOX_INIT, FeatureTest, Util } from "../shared/util.js";
|
||||
import {
|
||||
assert,
|
||||
BBOX_INIT,
|
||||
FeatureTest,
|
||||
shadow,
|
||||
Util,
|
||||
} from "../shared/util.js";
|
||||
import {
|
||||
CSS_FONT_INFO,
|
||||
FONT_INFO,
|
||||
@@ -47,15 +53,15 @@ class CssFontInfo {
|
||||
}
|
||||
|
||||
get fontFamily() {
|
||||
return this.#readString(0);
|
||||
return shadow(this, "fontFamily", this.#readString(0));
|
||||
}
|
||||
|
||||
get fontWeight() {
|
||||
return this.#readString(1);
|
||||
return shadow(this, "fontWeight", this.#readString(1));
|
||||
}
|
||||
|
||||
get italicAngle() {
|
||||
return this.#readString(2);
|
||||
return shadow(this, "italicAngle", this.#readString(2));
|
||||
}
|
||||
}
|
||||
|
||||
@@ -75,19 +81,19 @@ class SystemFontInfo {
|
||||
}
|
||||
|
||||
get css() {
|
||||
return this.#readString(0);
|
||||
return shadow(this, "css", this.#readString(0));
|
||||
}
|
||||
|
||||
get loadedName() {
|
||||
return this.#readString(1);
|
||||
return shadow(this, "loadedName", this.#readString(1));
|
||||
}
|
||||
|
||||
get baseFontName() {
|
||||
return this.#readString(2);
|
||||
return shadow(this, "baseFontName", this.#readString(2));
|
||||
}
|
||||
|
||||
get src() {
|
||||
return this.#readString(3);
|
||||
return shadow(this, "src", this.#readString(3));
|
||||
}
|
||||
|
||||
get style() {
|
||||
@@ -95,7 +101,7 @@ class SystemFontInfo {
|
||||
offset += 4 + this.#view.getUint32(offset);
|
||||
const style = readString(this.#buffer, this.#view, /* index = */ 0, offset),
|
||||
weight = readString(this.#buffer, this.#view, /* index = */ 1, offset);
|
||||
return { style, weight };
|
||||
return shadow(this, "style", { style, weight });
|
||||
}
|
||||
}
|
||||
|
||||
@@ -121,43 +127,43 @@ class FontInfo {
|
||||
}
|
||||
|
||||
get black() {
|
||||
return this.#readBoolean(0);
|
||||
return shadow(this, "black", this.#readBoolean(0));
|
||||
}
|
||||
|
||||
get bold() {
|
||||
return this.#readBoolean(1);
|
||||
return shadow(this, "bold", this.#readBoolean(1));
|
||||
}
|
||||
|
||||
get disableFontFace() {
|
||||
return this.#readBoolean(2);
|
||||
return shadow(this, "disableFontFace", this.#readBoolean(2));
|
||||
}
|
||||
|
||||
get fontExtraProperties() {
|
||||
return this.#readBoolean(3);
|
||||
return shadow(this, "fontExtraProperties", this.#readBoolean(3));
|
||||
}
|
||||
|
||||
get isInvalidPDFjsFont() {
|
||||
return this.#readBoolean(4);
|
||||
return shadow(this, "isInvalidPDFjsFont", this.#readBoolean(4));
|
||||
}
|
||||
|
||||
get isType3Font() {
|
||||
return this.#readBoolean(5);
|
||||
return shadow(this, "isType3Font", this.#readBoolean(5));
|
||||
}
|
||||
|
||||
get italic() {
|
||||
return this.#readBoolean(6);
|
||||
return shadow(this, "italic", this.#readBoolean(6));
|
||||
}
|
||||
|
||||
get missingFile() {
|
||||
return this.#readBoolean(7);
|
||||
return shadow(this, "missingFile", this.#readBoolean(7));
|
||||
}
|
||||
|
||||
get remeasure() {
|
||||
return this.#readBoolean(8);
|
||||
return shadow(this, "remeasure", this.#readBoolean(8));
|
||||
}
|
||||
|
||||
get vertical() {
|
||||
return this.#readBoolean(9);
|
||||
return shadow(this, "vertical", this.#readBoolean(9));
|
||||
}
|
||||
|
||||
#readNumber(index) {
|
||||
@@ -166,20 +172,19 @@ class FontInfo {
|
||||
}
|
||||
|
||||
get ascent() {
|
||||
return this.#readNumber(0);
|
||||
return shadow(this, "ascent", this.#readNumber(0));
|
||||
}
|
||||
|
||||
get descent() {
|
||||
return this.#readNumber(1);
|
||||
return shadow(this, "descent", this.#readNumber(1));
|
||||
}
|
||||
|
||||
#readArray(offset, arrLen, lookupName, increment) {
|
||||
const len = this.#view.getUint8(offset);
|
||||
const len = this.#view.getUint8(offset++);
|
||||
if (len === 0) {
|
||||
return undefined;
|
||||
}
|
||||
assert(len === arrLen, "Invalid array length.");
|
||||
offset += 1;
|
||||
const arr = new Array(len);
|
||||
for (let i = 0; i < len; i++) {
|
||||
arr[i] = this.#view[lookupName](offset, true);
|
||||
@@ -189,20 +194,28 @@ class FontInfo {
|
||||
}
|
||||
|
||||
get bbox() {
|
||||
return this.#readArray(
|
||||
/* offset = */ FONT_INFO.OFFSET_BBOX,
|
||||
/* arrLen = */ 4,
|
||||
/* lookup = */ "getInt16",
|
||||
/* increment = */ 2
|
||||
return shadow(
|
||||
this,
|
||||
"bbox",
|
||||
this.#readArray(
|
||||
/* offset = */ FONT_INFO.OFFSET_BBOX,
|
||||
/* arrLen = */ 4,
|
||||
/* lookup = */ "getInt16",
|
||||
/* increment = */ 2
|
||||
)
|
||||
);
|
||||
}
|
||||
|
||||
get fontMatrix() {
|
||||
return this.#readArray(
|
||||
/* offset = */ FONT_INFO.OFFSET_FONT_MATRIX,
|
||||
/* arrLen = */ 6,
|
||||
/* lookup = */ "getFloat64",
|
||||
/* increment = */ 8
|
||||
return shadow(
|
||||
this,
|
||||
"fontMatrix",
|
||||
this.#readArray(
|
||||
/* offset = */ FONT_INFO.OFFSET_FONT_MATRIX,
|
||||
/* arrLen = */ 6,
|
||||
/* lookup = */ "getFloat64",
|
||||
/* increment = */ 8
|
||||
)
|
||||
);
|
||||
}
|
||||
|
||||
@@ -217,44 +230,39 @@ class FontInfo {
|
||||
}
|
||||
|
||||
get fallbackName() {
|
||||
return this.#readString(0);
|
||||
return shadow(this, "fallbackName", this.#readString(0));
|
||||
}
|
||||
|
||||
get loadedName() {
|
||||
return this.#readString(1);
|
||||
}
|
||||
|
||||
get mimetype() {
|
||||
return this.#readString(2);
|
||||
return shadow(this, "loadedName", this.#readString(1));
|
||||
}
|
||||
|
||||
get name() {
|
||||
return this.#readString(3);
|
||||
return shadow(this, "name", this.#readString(2));
|
||||
}
|
||||
|
||||
#getDataOffsets() {
|
||||
#getBufferOffset(index) {
|
||||
let offset = FONT_INFO.OFFSET_STRINGS;
|
||||
const stringsLength = this.#view.getUint32(offset);
|
||||
offset += 4 + stringsLength;
|
||||
const systemFontInfoLength = this.#view.getUint32(offset);
|
||||
offset += 4 + systemFontInfoLength;
|
||||
const cssFontInfoLength = this.#view.getUint32(offset);
|
||||
offset += 4 + cssFontInfoLength;
|
||||
// We need to move past any string-data first, hence the `<=` condition.
|
||||
for (let i = 0; i <= index; i++) {
|
||||
offset += 4 + this.#view.getUint32(offset);
|
||||
}
|
||||
const length = this.#view.getUint32(offset);
|
||||
|
||||
return { offset, length };
|
||||
}
|
||||
|
||||
// NOTE: This cannot be shadowed, since it may be cleared.
|
||||
get data() {
|
||||
const { offset, length } = this.#getDataOffsets();
|
||||
return length === 0
|
||||
const { offset, length } = this.#getBufferOffset(2);
|
||||
return !length
|
||||
? undefined
|
||||
: new Uint8Array(this.#buffer, offset + 4, length);
|
||||
}
|
||||
|
||||
clearData() {
|
||||
const { offset, length } = this.#getDataOffsets();
|
||||
if (length === 0) {
|
||||
const { offset, length } = this.#getBufferOffset(2);
|
||||
if (!length) {
|
||||
return; // The data is either not present, or it was previously cleared.
|
||||
}
|
||||
this.#view.setUint32(offset, 0); // Zero the data-length.
|
||||
@@ -265,35 +273,23 @@ class FontInfo {
|
||||
}
|
||||
|
||||
get cssFontInfo() {
|
||||
let offset = FONT_INFO.OFFSET_STRINGS;
|
||||
const stringsLength = this.#view.getUint32(offset);
|
||||
offset += 4 + stringsLength;
|
||||
const systemFontInfoLength = this.#view.getUint32(offset);
|
||||
offset += 4 + systemFontInfoLength;
|
||||
const cssFontInfoLength = this.#view.getUint32(offset);
|
||||
if (cssFontInfoLength === 0) {
|
||||
return null;
|
||||
const { offset, length } = this.#getBufferOffset(1);
|
||||
let info = null;
|
||||
if (length) {
|
||||
const data = new Uint8Array(this.#buffer, offset + 4, length).slice();
|
||||
info = new CssFontInfo(data.buffer);
|
||||
}
|
||||
const cssFontInfoData = new Uint8Array(cssFontInfoLength);
|
||||
cssFontInfoData.set(
|
||||
new Uint8Array(this.#buffer, offset + 4, cssFontInfoLength)
|
||||
);
|
||||
return new CssFontInfo(cssFontInfoData.buffer);
|
||||
return shadow(this, "cssFontInfo", info);
|
||||
}
|
||||
|
||||
get systemFontInfo() {
|
||||
let offset = FONT_INFO.OFFSET_STRINGS;
|
||||
const stringsLength = this.#view.getUint32(offset);
|
||||
offset += 4 + stringsLength;
|
||||
const systemFontInfoLength = this.#view.getUint32(offset);
|
||||
if (systemFontInfoLength === 0) {
|
||||
return null;
|
||||
const { offset, length } = this.#getBufferOffset(0);
|
||||
let info = null;
|
||||
if (length) {
|
||||
const data = new Uint8Array(this.#buffer, offset + 4, length).slice();
|
||||
info = new SystemFontInfo(data.buffer);
|
||||
}
|
||||
const systemFontInfoData = new Uint8Array(systemFontInfoLength);
|
||||
systemFontInfoData.set(
|
||||
new Uint8Array(this.#buffer, offset + 4, systemFontInfoLength)
|
||||
);
|
||||
return new SystemFontInfo(systemFontInfoData.buffer);
|
||||
return shadow(this, "systemFontInfo", info);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -836,24 +836,52 @@ class TilingPattern {
|
||||
const ySize = dimy2.size;
|
||||
const tmpCanvas2 = owner.canvasFactory.create(xSize, ySize);
|
||||
const tmpCtx2 = tmpCanvas2.context;
|
||||
const ii = redrawHorizontally ? Math.floor(width / xstep) : 0;
|
||||
const jj = redrawVertically ? Math.floor(height / ystep) : 0;
|
||||
// Source rectangles outside the image contribute no pixels.
|
||||
const ii = redrawHorizontally
|
||||
? Math.min(Math.floor(width / xstep), Math.ceil(image.width / xSize))
|
||||
: 0;
|
||||
const jj = redrawVertically
|
||||
? Math.min(Math.floor(height / ystep), Math.ceil(image.height / ySize))
|
||||
: 0;
|
||||
|
||||
// Draw the overlapping parts of the original tile on the new tile.
|
||||
for (let i = 0; i <= ii; i++) {
|
||||
for (let j = 0; j <= jj; j++) {
|
||||
tmpCtx2.drawImage(
|
||||
// Fold rows, then columns, to avoid drawing every offset pair.
|
||||
// Descending indices draw the origin tile last.
|
||||
let rowSource = image;
|
||||
let bandCanvas = null;
|
||||
if (redrawVertically) {
|
||||
bandCanvas = owner.canvasFactory.create(image.width, ySize);
|
||||
const bandCtx = bandCanvas.context;
|
||||
for (let j = jj; j >= 0; j--) {
|
||||
bandCtx.drawImage(
|
||||
image,
|
||||
xSize * i,
|
||||
0,
|
||||
ySize * j,
|
||||
xSize,
|
||||
image.width,
|
||||
ySize,
|
||||
0,
|
||||
0,
|
||||
xSize,
|
||||
image.width,
|
||||
ySize
|
||||
);
|
||||
}
|
||||
rowSource = bandCanvas.canvas;
|
||||
}
|
||||
|
||||
for (let i = ii; i >= 0; i--) {
|
||||
tmpCtx2.drawImage(
|
||||
rowSource,
|
||||
xSize * i,
|
||||
0,
|
||||
xSize,
|
||||
ySize,
|
||||
0,
|
||||
0,
|
||||
xSize,
|
||||
ySize
|
||||
);
|
||||
}
|
||||
if (bandCanvas) {
|
||||
owner.canvasFactory.destroy(bandCanvas);
|
||||
}
|
||||
owner.canvasFactory.destroy(tmpCanvas);
|
||||
return {
|
||||
|
||||
@@ -39,7 +39,7 @@ class FONT_INFO {
|
||||
|
||||
static numbers = ["ascent", "descent"];
|
||||
|
||||
static strings = ["fallbackName", "loadedName", "mimetype", "name"];
|
||||
static strings = ["fallbackName", "loadedName", "name"];
|
||||
|
||||
static OFFSET_NUMBERS = Math.ceil((this.bools.length * 2) / 8);
|
||||
|
||||
|
||||
@@ -959,3 +959,6 @@
|
||||
!nonembedded_type1_tounicode.pdf
|
||||
!transfer_maps.pdf
|
||||
!resetform_parent.pdf
|
||||
!tiling-pattern-tiny-steps.pdf
|
||||
!tiling-pattern-tiny-steps-large.pdf
|
||||
!tiling-pattern-fold-order.pdf
|
||||
|
||||
@@ -0,0 +1,36 @@
|
||||
%PDF-1.7
|
||||
%âãÏÓ
|
||||
1 0 obj
|
||||
<< /Type /Catalog /Pages 2 0 R >>
|
||||
endobj
|
||||
2 0 obj
|
||||
<< /Type /Pages /Kids [3 0 R] /Count 1 >>
|
||||
endobj
|
||||
3 0 obj
|
||||
<< /Type /Page /Parent 2 0 R /MediaBox [0 0 20 20] /Resources << /Pattern << /P1 4 0 R >> >> /Contents 5 0 R >>
|
||||
endobj
|
||||
4 0 obj
|
||||
<< /PatternType 1 /PaintType 1 /TilingType 1 /BBox [0 0 20 20] /XStep 10 /YStep 10 /Resources << >> /Length 49 >>
|
||||
stream
|
||||
1 0 0 rg 0 0 10 10 re f 0 0 1 rg 10 10 10 10 re f
|
||||
endstream
|
||||
endobj
|
||||
5 0 obj
|
||||
<< /Length 38 >>
|
||||
stream
|
||||
q /Pattern cs /P1 scn 0 0 20 20 re f Q
|
||||
endstream
|
||||
endobj
|
||||
xref
|
||||
0 6
|
||||
0000000000 65535 f
|
||||
0000000015 00000 n
|
||||
0000000064 00000 n
|
||||
0000000121 00000 n
|
||||
0000000248 00000 n
|
||||
0000000444 00000 n
|
||||
trailer
|
||||
<< /Size 6 /Root 1 0 R >>
|
||||
startxref
|
||||
532
|
||||
%%EOF
|
||||
@@ -0,0 +1,36 @@
|
||||
%PDF-1.7
|
||||
%âãÏÓ
|
||||
1 0 obj
|
||||
<< /Type /Catalog /Pages 2 0 R >>
|
||||
endobj
|
||||
2 0 obj
|
||||
<< /Type /Pages /Kids [3 0 R] /Count 1 >>
|
||||
endobj
|
||||
3 0 obj
|
||||
<< /Type /Page /Parent 2 0 R /MediaBox [0 0 1200 1200] /Resources << /Pattern << /P1 4 0 R >> >> /Contents 5 0 R >>
|
||||
endobj
|
||||
4 0 obj
|
||||
<< /PatternType 1 /PaintType 1 /TilingType 1 /BBox [0 0 1200 1200] /XStep 0.001 /YStep 0.001 /Resources << >> /Length 26 >>
|
||||
stream
|
||||
q 1100 1100 100 100 re f Q
|
||||
endstream
|
||||
endobj
|
||||
5 0 obj
|
||||
<< /Length 42 >>
|
||||
stream
|
||||
q /Pattern cs /P1 scn 0 0 1200 1200 re f Q
|
||||
endstream
|
||||
endobj
|
||||
xref
|
||||
0 6
|
||||
0000000000 65535 f
|
||||
0000000015 00000 n
|
||||
0000000064 00000 n
|
||||
0000000121 00000 n
|
||||
0000000252 00000 n
|
||||
0000000435 00000 n
|
||||
trailer
|
||||
<< /Size 6 /Root 1 0 R >>
|
||||
startxref
|
||||
527
|
||||
%%EOF
|
||||
@@ -0,0 +1,35 @@
|
||||
%PDF-1.7
|
||||
1 0 obj
|
||||
<< /Type /Catalog /Pages 2 0 R >>
|
||||
endobj
|
||||
2 0 obj
|
||||
<< /Type /Pages /Kids [3 0 R] /Count 1 >>
|
||||
endobj
|
||||
3 0 obj
|
||||
<< /Type /Page /Parent 2 0 R /MediaBox [0 0 200 200] /Resources << /Pattern << /P1 4 0 R >> >> /Contents 5 0 R >>
|
||||
endobj
|
||||
4 0 obj
|
||||
<< /PatternType 1 /PaintType 1 /TilingType 1 /BBox [0 0 10 10] /XStep 0.001 /YStep 0.001 /Resources << >> /Length 19 >>
|
||||
stream
|
||||
q 0 0 10 10 re f Q
|
||||
endstream
|
||||
endobj
|
||||
5 0 obj
|
||||
<< /Length 41 >>
|
||||
stream
|
||||
q /Pattern cs /P1 scn 0 0 200 200 re f Q
|
||||
endstream
|
||||
endobj
|
||||
xref
|
||||
0 6
|
||||
0000000000 65535 f
|
||||
0000000009 00000 n
|
||||
0000000058 00000 n
|
||||
0000000115 00000 n
|
||||
0000000244 00000 n
|
||||
0000000415 00000 n
|
||||
trailer
|
||||
<< /Size 6 /Root 1 0 R >>
|
||||
startxref
|
||||
505
|
||||
%%EOF
|
||||
@@ -239,3 +239,89 @@ describe("custom ownerDocument", function () {
|
||||
expect(ownerDocument.adoptedStyleSheets.length).toBe(0);
|
||||
});
|
||||
});
|
||||
|
||||
describe("tiling pattern rendering", function () {
|
||||
// The old folding loops required (10 / 0.001 + 1)^2 = 100,020,001 draws.
|
||||
it("does not hang on tiny XStep/YStep steps", async function () {
|
||||
const loadingTask = getDocument(
|
||||
buildGetDocumentParams("tiling-pattern-tiny-steps.pdf")
|
||||
);
|
||||
const doc = await loadingTask.promise;
|
||||
const page = await doc.getPage(1);
|
||||
|
||||
const viewport = page.getViewport({ scale: 1 });
|
||||
const { canvasFactory } = doc;
|
||||
const canvasAndCtx = canvasFactory.create(viewport.width, viewport.height);
|
||||
|
||||
await page.render({
|
||||
canvas: canvasAndCtx.canvas,
|
||||
viewport,
|
||||
}).promise;
|
||||
|
||||
expect(getTopLeftPixel(canvasAndCtx.context)).toEqual({
|
||||
r: 0,
|
||||
g: 0,
|
||||
b: 0,
|
||||
a: 255,
|
||||
});
|
||||
|
||||
canvasFactory.destroy(canvasAndCtx);
|
||||
await loadingTask.destroy();
|
||||
});
|
||||
|
||||
// Only the tile's far 100x100 corner is painted.
|
||||
it("does not hang and keeps far-corner content on a large BBox with tiny steps", async function () {
|
||||
const loadingTask = getDocument(
|
||||
buildGetDocumentParams("tiling-pattern-tiny-steps-large.pdf")
|
||||
);
|
||||
const doc = await loadingTask.promise;
|
||||
const page = await doc.getPage(1);
|
||||
|
||||
const viewport = page.getViewport({ scale: 1 });
|
||||
const { canvasFactory } = doc;
|
||||
const canvasAndCtx = canvasFactory.create(viewport.width, viewport.height);
|
||||
|
||||
await page.render({
|
||||
canvas: canvasAndCtx.canvas,
|
||||
viewport,
|
||||
}).promise;
|
||||
|
||||
expect(getTopLeftPixel(canvasAndCtx.context)).toEqual({
|
||||
r: 0,
|
||||
g: 0,
|
||||
b: 0,
|
||||
a: 255,
|
||||
});
|
||||
|
||||
canvasFactory.destroy(canvasAndCtx);
|
||||
await loadingTask.destroy();
|
||||
});
|
||||
|
||||
// The red and blue squares coincide after folding, exposing draw order.
|
||||
it("places the origin tile on top when tiles overlap", async function () {
|
||||
const loadingTask = getDocument(
|
||||
buildGetDocumentParams("tiling-pattern-fold-order.pdf")
|
||||
);
|
||||
const doc = await loadingTask.promise;
|
||||
const page = await doc.getPage(1);
|
||||
|
||||
const viewport = page.getViewport({ scale: 1 });
|
||||
const { canvasFactory } = doc;
|
||||
const canvasAndCtx = canvasFactory.create(viewport.width, viewport.height);
|
||||
|
||||
await page.render({
|
||||
canvas: canvasAndCtx.canvas,
|
||||
viewport,
|
||||
}).promise;
|
||||
|
||||
expect(getTopLeftPixel(canvasAndCtx.context)).toEqual({
|
||||
r: 255,
|
||||
g: 0,
|
||||
b: 0,
|
||||
a: 255,
|
||||
});
|
||||
|
||||
canvasFactory.destroy(canvasAndCtx);
|
||||
await loadingTask.destroy();
|
||||
});
|
||||
});
|
||||
|
||||
@@ -70,7 +70,6 @@ describe("obj_bin_transform", function () {
|
||||
fontMatrix: [1, 1, 1, 1, 1, 1],
|
||||
fallbackName: "string",
|
||||
loadedName: "string",
|
||||
mimetype: "string",
|
||||
name: "string",
|
||||
data: new Uint8Array([1, 2, 3, 4, 5, 6, 7, 8, 9, 10]),
|
||||
uselessProp: "something",
|
||||
@@ -124,7 +123,7 @@ describe("obj_bin_transform", function () {
|
||||
|
||||
describe("FontInfo", function () {
|
||||
it("must roundtrip correctly for FontInfo", function () {
|
||||
let sizeEstimate = 77; // fixed offset until the strings
|
||||
let sizeEstimate = 67; // fixed offset until the strings
|
||||
const { encoder } = InfoUtils;
|
||||
sizeEstimate += 4 + 4 * (4 + encoder.encode("string").length);
|
||||
sizeEstimate += 4 + 4; // cssFontInfo and systemFontInfo
|
||||
@@ -148,7 +147,6 @@ describe("obj_bin_transform", function () {
|
||||
expect(deserialized.fontMatrix).toEqual([1, 1, 1, 1, 1, 1]);
|
||||
expect(deserialized.fallbackName).toEqual("string");
|
||||
expect(deserialized.loadedName).toEqual("string");
|
||||
expect(deserialized.mimetype).toEqual("string");
|
||||
expect(deserialized.name).toEqual("string");
|
||||
expect(Array.from(deserialized.data)).toEqual([
|
||||
1, 2, 3, 4, 5, 6, 7, 8, 9, 10,
|
||||
|
||||
Reference in New Issue
Block a user