Skip to content

Commit 9870d89

Browse files
authored
Merge pull request #20640 from calixteman/issue20629
Set a pages mapper per loaded document
2 parents babd030 + 4b4ab10 commit 9870d89

9 files changed

Lines changed: 104 additions & 80 deletions

File tree

src/display/api.js

Lines changed: 37 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -233,6 +233,9 @@ const RENDERING_CANCELLED_TIMEOUT = 100; // ms
233233
* The default value is {DOMFilterFactory}.
234234
* @property {boolean} [enableHWA] - Enables hardware acceleration for
235235
* rendering. The default value is `false`.
236+
* @property {Object} [pagesMapper] - The pages mapper that will be used to map
237+
* page ids and page numbers. It's used when the page order is changed or some
238+
* pages are removed, cloned, etc.
236239
*/
237240

238241
/**
@@ -342,6 +345,7 @@ function getDocument(src = {}) {
342345
: DOMFilterFactory);
343346
const enableHWA = src.enableHWA === true;
344347
const useWasm = src.useWasm !== false;
348+
const pagesMapper = src.pagesMapper || new PagesMapper();
345349

346350
// Parameters whose default values depend on other parameters.
347351
const length = rangeTransport ? rangeTransport.length : (src.length ?? NaN);
@@ -511,7 +515,8 @@ function getDocument(src = {}) {
511515
task,
512516
networkStream,
513517
transportParams,
514-
transportFactory
518+
transportFactory,
519+
pagesMapper
515520
);
516521
task._transport = transport;
517522
messageHandler.send("Ready", null);
@@ -761,6 +766,13 @@ class PDFDocumentProxy {
761766
}
762767
}
763768

769+
/**
770+
* @type {PagesMapper} The pages mapper instance.
771+
*/
772+
get pagesMapper() {
773+
return this._transport.pagesMapper;
774+
}
775+
764776
/**
765777
* @type {AnnotationStorage} Storage for annotation data in forms.
766778
*/
@@ -1324,9 +1336,9 @@ class PDFDocumentProxy {
13241336
class PDFPageProxy {
13251337
#pendingCleanup = false;
13261338

1327-
#pagesMapper = PagesMapper.instance;
1339+
#pagesMapper = null;
13281340

1329-
constructor(pageIndex, pageInfo, transport, pdfBug = false) {
1341+
constructor(pageIndex, pageInfo, transport, pagesMapper, pdfBug = false) {
13301342
this._pageIndex = pageIndex;
13311343
this._pageInfo = pageInfo;
13321344
this._transport = transport;
@@ -1339,6 +1351,7 @@ class PDFPageProxy {
13391351
this._intentStates = new Map();
13401352
this.destroyed = false;
13411353
this.recordedBBoxes = null;
1354+
this.#pagesMapper = pagesMapper;
13421355
}
13431356

13441357
/**
@@ -2402,9 +2415,14 @@ class WorkerTransport {
24022415

24032416
#passwordCapability = null;
24042417

2405-
#pagesMapper = PagesMapper.instance;
2406-
2407-
constructor(messageHandler, loadingTask, networkStream, params, factory) {
2418+
constructor(
2419+
messageHandler,
2420+
loadingTask,
2421+
networkStream,
2422+
params,
2423+
factory,
2424+
pagesMapper
2425+
) {
24082426
this.messageHandler = messageHandler;
24092427
this.loadingTask = loadingTask;
24102428
this.#networkStream = networkStream;
@@ -2429,7 +2447,8 @@ class WorkerTransport {
24292447

24302448
this.setupMessageHandler();
24312449

2432-
this.#pagesMapper.addListener(this.#updateCaches.bind(this));
2450+
this.pagesMapper = pagesMapper;
2451+
this.pagesMapper.addListener(this.#updateCaches.bind(this));
24332452

24342453
if (typeof PDFJSDev === "undefined" || PDFJSDev.test("TESTING")) {
24352454
// For testing purposes.
@@ -2458,8 +2477,8 @@ class WorkerTransport {
24582477
#updateCaches() {
24592478
const newPageCache = new Map();
24602479
const newPromiseCache = new Map();
2461-
for (let i = 0, ii = this.#pagesMapper.pagesNumber; i < ii; i++) {
2462-
const prevPageIndex = this.#pagesMapper.getPrevPageNumber(i + 1) - 1;
2480+
for (let i = 0, ii = this.pagesMapper.pagesNumber; i < ii; i++) {
2481+
const prevPageIndex = this.pagesMapper.getPrevPageNumber(i + 1) - 1;
24632482
const page = this.#pageCache.get(prevPageIndex);
24642483
if (page) {
24652484
newPageCache.set(i, page);
@@ -2730,7 +2749,7 @@ class WorkerTransport {
27302749
});
27312750

27322751
messageHandler.on("GetDoc", ({ pdfInfo }) => {
2733-
this.#pagesMapper.pagesNumber = pdfInfo.numPages;
2752+
this.pagesMapper.pagesNumber = pdfInfo.numPages;
27342753
this._numPages = pdfInfo.numPages;
27352754
this._htmlForXfa = pdfInfo.htmlForXfa;
27362755
delete pdfInfo.htmlForXfa;
@@ -2947,12 +2966,12 @@ class WorkerTransport {
29472966
if (
29482967
!Number.isInteger(pageNumber) ||
29492968
pageNumber <= 0 ||
2950-
pageNumber > this.#pagesMapper.pagesNumber
2969+
pageNumber > this.pagesMapper.pagesNumber
29512970
) {
29522971
return Promise.reject(new Error("Invalid page request."));
29532972
}
29542973
const pageIndex = pageNumber - 1;
2955-
const newPageIndex = this.#pagesMapper.getPageId(pageNumber) - 1;
2974+
const newPageIndex = this.pagesMapper.getPageId(pageNumber) - 1;
29562975

29572976
const cachedPromise = this.#pagePromises.get(pageIndex);
29582977
if (cachedPromise) {
@@ -2974,6 +2993,7 @@ class WorkerTransport {
29742993
pageIndex,
29752994
pageInfo,
29762995
this,
2996+
this.pagesMapper,
29772997
this._params.pdfBug
29782998
);
29792999
this.#pageCache.set(pageIndex, page);
@@ -2991,12 +3011,12 @@ class WorkerTransport {
29913011
num: ref.num,
29923012
gen: ref.gen,
29933013
});
2994-
return this.#pagesMapper.getPageNumber(index + 1) - 1;
3014+
return this.pagesMapper.getPageNumber(index + 1) - 1;
29953015
}
29963016

29973017
getAnnotations(pageIndex, intent) {
29983018
return this.messageHandler.sendWithPromise("GetAnnotations", {
2999-
pageIndex: this.#pagesMapper.getPageId(pageIndex + 1) - 1,
3019+
pageIndex: this.pagesMapper.getPageId(pageIndex + 1) - 1,
30003020
intent,
30013021
});
30023022
}
@@ -3063,13 +3083,13 @@ class WorkerTransport {
30633083

30643084
getPageJSActions(pageIndex) {
30653085
return this.messageHandler.sendWithPromise("GetPageJSActions", {
3066-
pageIndex: this.#pagesMapper.getPageId(pageIndex + 1) - 1,
3086+
pageIndex: this.pagesMapper.getPageId(pageIndex + 1) - 1,
30673087
});
30683088
}
30693089

30703090
getStructTree(pageIndex) {
30713091
return this.messageHandler.sendWithPromise("GetStructTree", {
3072-
pageIndex: this.#pagesMapper.getPageId(pageIndex + 1) - 1,
3092+
pageIndex: this.pagesMapper.getPageId(pageIndex + 1) - 1,
30733093
});
30743094
}
30753095

@@ -3141,7 +3161,7 @@ class WorkerTransport {
31413161
const refStr = ref.gen === 0 ? `${ref.num}R` : `${ref.num}R${ref.gen}`;
31423162
const pageIndex = this.#pageRefCache.get(refStr);
31433163
return pageIndex >= 0
3144-
? this.#pagesMapper.getPageNumber(pageIndex + 1)
3164+
? this.pagesMapper.getPageNumber(pageIndex + 1)
31453165
: null;
31463166
}
31473167
}

src/display/display_utils.js

Lines changed: 30 additions & 43 deletions
Original file line numberDiff line numberDiff line change
@@ -1045,38 +1045,38 @@ class PagesMapper {
10451045
* Maps page IDs to their corresponding page numbers.
10461046
* @type {Uint32Array|null}
10471047
*/
1048-
static #idToPageNumber = null;
1048+
#idToPageNumber = null;
10491049

10501050
/**
10511051
* Maps page numbers to their corresponding page IDs.
10521052
* @type {Uint32Array|null}
10531053
*/
1054-
static #pageNumberToId = null;
1054+
#pageNumberToId = null;
10551055

10561056
/**
10571057
* Previous mapping of page IDs to page numbers.
10581058
* @type {Uint32Array|null}
10591059
*/
1060-
static #prevIdToPageNumber = null;
1060+
#prevIdToPageNumber = null;
10611061

10621062
/**
10631063
* The total number of pages.
10641064
* @type {number}
10651065
*/
1066-
static #pagesNumber = 0;
1066+
#pagesNumber = 0;
10671067

10681068
/**
10691069
* Listeners for page changes.
10701070
* @type {Array<function>}
10711071
*/
1072-
static #listeners = [];
1072+
#listeners = [];
10731073

10741074
/**
10751075
* Gets the total number of pages.
10761076
* @returns {number} The number of pages.
10771077
*/
10781078
get pagesNumber() {
1079-
return PagesMapper.#pagesNumber;
1079+
return this.#pagesNumber;
10801080
}
10811081

10821082
/**
@@ -1085,52 +1085,49 @@ class PagesMapper {
10851085
* @param {number} n - The total number of pages.
10861086
*/
10871087
set pagesNumber(n) {
1088-
if (PagesMapper.#pagesNumber === n) {
1088+
if (this.#pagesNumber === n) {
10891089
return;
10901090
}
1091-
PagesMapper.#pagesNumber = n;
1091+
this.#pagesNumber = n;
10921092
if (n === 0) {
1093-
PagesMapper.#pageNumberToId = null;
1094-
PagesMapper.#idToPageNumber = null;
1093+
this.#pageNumberToId = null;
1094+
this.#idToPageNumber = null;
10951095
}
10961096
}
10971097

10981098
addListener(listener) {
1099-
PagesMapper.#listeners.push(listener);
1099+
this.#listeners.push(listener);
11001100
}
11011101

11021102
removeListener(listener) {
1103-
const index = PagesMapper.#listeners.indexOf(listener);
1103+
const index = this.#listeners.indexOf(listener);
11041104
if (index >= 0) {
1105-
PagesMapper.#listeners.splice(index, 1);
1105+
this.#listeners.splice(index, 1);
11061106
}
11071107
}
11081108

11091109
#updateListeners() {
1110-
for (const listener of PagesMapper.#listeners) {
1110+
for (const listener of this.#listeners) {
11111111
listener();
11121112
}
11131113
}
11141114

11151115
#init(mustInit) {
1116-
if (PagesMapper.#pageNumberToId) {
1116+
if (this.#pageNumberToId) {
11171117
return;
11181118
}
1119-
const n = PagesMapper.#pagesNumber;
1119+
const n = this.#pagesNumber;
11201120

11211121
// Allocate a single array for better memory locality.
11221122
const array = new Uint32Array(3 * n);
1123-
const pageNumberToId = (PagesMapper.#pageNumberToId = array.subarray(0, n));
1124-
const idToPageNumber = (PagesMapper.#idToPageNumber = array.subarray(
1125-
n,
1126-
2 * n
1127-
));
1123+
const pageNumberToId = (this.#pageNumberToId = array.subarray(0, n));
1124+
const idToPageNumber = (this.#idToPageNumber = array.subarray(n, 2 * n));
11281125
if (mustInit) {
11291126
for (let i = 0; i < n; i++) {
11301127
pageNumberToId[i] = idToPageNumber[i] = i + 1;
11311128
}
11321129
}
1133-
PagesMapper.#prevIdToPageNumber = array.subarray(2 * n);
1130+
this.#prevIdToPageNumber = array.subarray(2 * n);
11341131
}
11351132

11361133
/**
@@ -1143,9 +1140,9 @@ class PagesMapper {
11431140
*/
11441141
movePages(selectedPages, pagesToMove, index) {
11451142
this.#init(true);
1146-
const pageNumberToId = PagesMapper.#pageNumberToId;
1147-
const idToPageNumber = PagesMapper.#idToPageNumber;
1148-
PagesMapper.#prevIdToPageNumber.set(idToPageNumber);
1143+
const pageNumberToId = this.#pageNumberToId;
1144+
const idToPageNumber = this.#idToPageNumber;
1145+
this.#prevIdToPageNumber.set(idToPageNumber);
11491146
const movedCount = pagesToMove.length;
11501147
const mappedPagesToMove = new Uint32Array(movedCount);
11511148
let removedBeforeTarget = 0;
@@ -1158,7 +1155,7 @@ class PagesMapper {
11581155
}
11591156
}
11601157

1161-
const pagesNumber = PagesMapper.#pagesNumber;
1158+
const pagesNumber = this.#pagesNumber;
11621159
// target index after removing elements that were before it
11631160
let adjustedTarget = index - removedBeforeTarget;
11641161
const remainingLen = pagesNumber - movedCount;
@@ -1201,7 +1198,7 @@ class PagesMapper {
12011198
* @returns {boolean} True if the mappings have been altered, false otherwise.
12021199
*/
12031200
hasBeenAltered() {
1204-
return PagesMapper.#pageNumberToId !== null;
1201+
return this.#pageNumberToId !== null;
12051202
}
12061203

12071204
/**
@@ -1211,16 +1208,14 @@ class PagesMapper {
12111208
getPageMappingForSaving() {
12121209
// Saving is index-based.
12131210
return {
1214-
pageIndices: PagesMapper.#idToPageNumber
1215-
? PagesMapper.#idToPageNumber.map(x => x - 1)
1211+
pageIndices: this.#idToPageNumber
1212+
? this.#idToPageNumber.map(x => x - 1)
12161213
: null,
12171214
};
12181215
}
12191216

12201217
getPrevPageNumber(pageNumber) {
1221-
return PagesMapper.#prevIdToPageNumber[
1222-
PagesMapper.#pageNumberToId[pageNumber - 1] - 1
1223-
];
1218+
return this.#prevIdToPageNumber[this.#pageNumberToId[pageNumber - 1] - 1];
12241219
}
12251220

12261221
/**
@@ -1229,7 +1224,7 @@ class PagesMapper {
12291224
* @returns {number} The page number, or the ID itself if no mapping exists.
12301225
*/
12311226
getPageNumber(id) {
1232-
return PagesMapper.#idToPageNumber?.[id - 1] ?? id;
1227+
return this.#idToPageNumber?.[id - 1] ?? id;
12331228
}
12341229

12351230
/**
@@ -1239,19 +1234,11 @@ class PagesMapper {
12391234
* exists.
12401235
*/
12411236
getPageId(pageNumber) {
1242-
return PagesMapper.#pageNumberToId?.[pageNumber - 1] ?? pageNumber;
1243-
}
1244-
1245-
/**
1246-
* Gets or creates a singleton instance of PagesMapper.
1247-
* @returns {PagesMapper} The singleton instance.
1248-
*/
1249-
static get instance() {
1250-
return shadow(this, "instance", new PagesMapper());
1237+
return this.#pageNumberToId?.[pageNumber - 1] ?? pageNumber;
12511238
}
12521239

12531240
getMapping() {
1254-
return PagesMapper.#pageNumberToId.subarray(0, this.pagesNumber);
1241+
return this.#pageNumberToId.subarray(0, this.pagesNumber);
12551242
}
12561243
}
12571244

src/pdf.js

Lines changed: 0 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -57,7 +57,6 @@ import {
5757
isPdfFile,
5858
noContextMenu,
5959
OutputScale,
60-
PagesMapper,
6160
PDFDateString,
6261
PixelsPerInch,
6362
RenderingCancelledException,
@@ -129,7 +128,6 @@ globalThis.pdfjsLib = {
129128
normalizeUnicode,
130129
OPS,
131130
OutputScale,
132-
PagesMapper,
133131
PasswordResponses,
134132
PDFDataRangeTransport,
135133
PDFDateString,
@@ -189,7 +187,6 @@ export {
189187
normalizeUnicode,
190188
OPS,
191189
OutputScale,
192-
PagesMapper,
193190
PasswordResponses,
194191
PDFDataRangeTransport,
195192
PDFDateString,

0 commit comments

Comments
 (0)