Skip to content

Commit e91b480

Browse files
committed
Move the PDFObjects class to its own file
This isn't directly part of the official API, and having this class in its own file could help avoid future changes (e.g. issue 18148) affecting the size of the `src/display/api.js` file unnecessarily.
1 parent 0105237 commit e91b480

File tree

2 files changed

+126
-109
lines changed

2 files changed

+126
-109
lines changed

src/display/api.js

Lines changed: 1 addition & 109 deletions
Original file line numberDiff line numberDiff line change
@@ -73,6 +73,7 @@ import { PDFDataTransportStream } from "./transport_stream.js";
7373
import { PDFFetchStream } from "display-fetch_stream";
7474
import { PDFNetworkStream } from "display-network";
7575
import { PDFNodeStream } from "display-node_stream";
76+
import { PDFObjects } from "./pdf_objects.js";
7677
import { TextLayer } from "./text_layer.js";
7778
import { XfaText } from "./xfa_text.js";
7879

@@ -3010,115 +3011,6 @@ class WorkerTransport {
30103011
}
30113012
}
30123013

3013-
const INITIAL_DATA = Symbol("INITIAL_DATA");
3014-
3015-
/**
3016-
* A PDF document and page is built of many objects. E.g. there are objects for
3017-
* fonts, images, rendering code, etc. These objects may get processed inside of
3018-
* a worker. This class implements some basic methods to manage these objects.
3019-
*/
3020-
class PDFObjects {
3021-
#objs = Object.create(null);
3022-
3023-
/**
3024-
* Ensures there is an object defined for `objId`.
3025-
*
3026-
* @param {string} objId
3027-
* @returns {Object}
3028-
*/
3029-
#ensureObj(objId) {
3030-
return (this.#objs[objId] ||= {
3031-
...Promise.withResolvers(),
3032-
data: INITIAL_DATA,
3033-
});
3034-
}
3035-
3036-
/**
3037-
* If called *without* callback, this returns the data of `objId` but the
3038-
* object needs to be resolved. If it isn't, this method throws.
3039-
*
3040-
* If called *with* a callback, the callback is called with the data of the
3041-
* object once the object is resolved. That means, if you call this method
3042-
* and the object is already resolved, the callback gets called right away.
3043-
*
3044-
* @param {string} objId
3045-
* @param {function} [callback]
3046-
* @returns {any}
3047-
*/
3048-
get(objId, callback = null) {
3049-
// If there is a callback, then the get can be async and the object is
3050-
// not required to be resolved right now.
3051-
if (callback) {
3052-
const obj = this.#ensureObj(objId);
3053-
obj.promise.then(() => callback(obj.data));
3054-
return null;
3055-
}
3056-
// If there isn't a callback, the user expects to get the resolved data
3057-
// directly.
3058-
const obj = this.#objs[objId];
3059-
// If there isn't an object yet or the object isn't resolved, then the
3060-
// data isn't ready yet!
3061-
if (!obj || obj.data === INITIAL_DATA) {
3062-
throw new Error(`Requesting object that isn't resolved yet ${objId}.`);
3063-
}
3064-
return obj.data;
3065-
}
3066-
3067-
/**
3068-
* @param {string} objId
3069-
* @returns {boolean}
3070-
*/
3071-
has(objId) {
3072-
const obj = this.#objs[objId];
3073-
return !!obj && obj.data !== INITIAL_DATA;
3074-
}
3075-
3076-
/**
3077-
* @param {string} objId
3078-
* @returns {boolean}
3079-
*/
3080-
delete(objId) {
3081-
const obj = this.#objs[objId];
3082-
if (!obj || obj.data === INITIAL_DATA) {
3083-
// Only allow removing the object *after* it's been resolved.
3084-
return false;
3085-
}
3086-
delete this.#objs[objId];
3087-
return true;
3088-
}
3089-
3090-
/**
3091-
* Resolves the object `objId` with optional `data`.
3092-
*
3093-
* @param {string} objId
3094-
* @param {any} [data]
3095-
*/
3096-
resolve(objId, data = null) {
3097-
const obj = this.#ensureObj(objId);
3098-
obj.data = data;
3099-
obj.resolve();
3100-
}
3101-
3102-
clear() {
3103-
for (const objId in this.#objs) {
3104-
const { data } = this.#objs[objId];
3105-
data?.bitmap?.close(); // Release any `ImageBitmap` data.
3106-
}
3107-
this.#objs = Object.create(null);
3108-
}
3109-
3110-
*[Symbol.iterator]() {
3111-
for (const objId in this.#objs) {
3112-
const { data } = this.#objs[objId];
3113-
3114-
if (data === INITIAL_DATA) {
3115-
continue;
3116-
}
3117-
yield [objId, data];
3118-
}
3119-
}
3120-
}
3121-
31223014
/**
31233015
* Allows controlling of the rendering tasks.
31243016
*/

src/display/pdf_objects.js

Lines changed: 125 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,125 @@
1+
/* Copyright 2012 Mozilla Foundation
2+
*
3+
* Licensed under the Apache License, Version 2.0 (the "License");
4+
* you may not use this file except in compliance with the License.
5+
* You may obtain a copy of the License at
6+
*
7+
* http://www.apache.org/licenses/LICENSE-2.0
8+
*
9+
* Unless required by applicable law or agreed to in writing, software
10+
* distributed under the License is distributed on an "AS IS" BASIS,
11+
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12+
* See the License for the specific language governing permissions and
13+
* limitations under the License.
14+
*/
15+
16+
const INITIAL_DATA = Symbol("INITIAL_DATA");
17+
18+
/**
19+
* A PDF document and page is built of many objects. E.g. there are objects for
20+
* fonts, images, rendering code, etc. These objects may get processed inside of
21+
* a worker. This class implements some basic methods to manage these objects.
22+
*/
23+
class PDFObjects {
24+
#objs = Object.create(null);
25+
26+
/**
27+
* Ensures there is an object defined for `objId`.
28+
*
29+
* @param {string} objId
30+
* @returns {Object}
31+
*/
32+
#ensureObj(objId) {
33+
return (this.#objs[objId] ||= {
34+
...Promise.withResolvers(),
35+
data: INITIAL_DATA,
36+
});
37+
}
38+
39+
/**
40+
* If called *without* callback, this returns the data of `objId` but the
41+
* object needs to be resolved. If it isn't, this method throws.
42+
*
43+
* If called *with* a callback, the callback is called with the data of the
44+
* object once the object is resolved. That means, if you call this method
45+
* and the object is already resolved, the callback gets called right away.
46+
*
47+
* @param {string} objId
48+
* @param {function} [callback]
49+
* @returns {any}
50+
*/
51+
get(objId, callback = null) {
52+
// If there is a callback, then the get can be async and the object is
53+
// not required to be resolved right now.
54+
if (callback) {
55+
const obj = this.#ensureObj(objId);
56+
obj.promise.then(() => callback(obj.data));
57+
return null;
58+
}
59+
// If there isn't a callback, the user expects to get the resolved data
60+
// directly.
61+
const obj = this.#objs[objId];
62+
// If there isn't an object yet or the object isn't resolved, then the
63+
// data isn't ready yet!
64+
if (!obj || obj.data === INITIAL_DATA) {
65+
throw new Error(`Requesting object that isn't resolved yet ${objId}.`);
66+
}
67+
return obj.data;
68+
}
69+
70+
/**
71+
* @param {string} objId
72+
* @returns {boolean}
73+
*/
74+
has(objId) {
75+
const obj = this.#objs[objId];
76+
return !!obj && obj.data !== INITIAL_DATA;
77+
}
78+
79+
/**
80+
* @param {string} objId
81+
* @returns {boolean}
82+
*/
83+
delete(objId) {
84+
const obj = this.#objs[objId];
85+
if (!obj || obj.data === INITIAL_DATA) {
86+
// Only allow removing the object *after* it's been resolved.
87+
return false;
88+
}
89+
delete this.#objs[objId];
90+
return true;
91+
}
92+
93+
/**
94+
* Resolves the object `objId` with optional `data`.
95+
*
96+
* @param {string} objId
97+
* @param {any} [data]
98+
*/
99+
resolve(objId, data = null) {
100+
const obj = this.#ensureObj(objId);
101+
obj.data = data;
102+
obj.resolve();
103+
}
104+
105+
clear() {
106+
for (const objId in this.#objs) {
107+
const { data } = this.#objs[objId];
108+
data?.bitmap?.close(); // Release any `ImageBitmap` data.
109+
}
110+
this.#objs = Object.create(null);
111+
}
112+
113+
*[Symbol.iterator]() {
114+
for (const objId in this.#objs) {
115+
const { data } = this.#objs[objId];
116+
117+
if (data === INITIAL_DATA) {
118+
continue;
119+
}
120+
yield [objId, data];
121+
}
122+
}
123+
}
124+
125+
export { PDFObjects };

0 commit comments

Comments
 (0)