@epam/pdf-highlighter-kit 0.0.13 → 0.0.17
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/PDFHighlightViewer.d.ts +12 -2
- package/dist/PDFHighlightViewer.d.ts.map +1 -1
- package/dist/PDFHighlightViewer.js +140 -39
- package/dist/PDFHighlightViewer.js.map +1 -1
- package/dist/api.d.ts +7 -1
- package/dist/api.d.ts.map +1 -1
- package/dist/core/pdf-engine.d.ts +3 -1
- package/dist/core/pdf-engine.d.ts.map +1 -1
- package/dist/core/pdf-engine.js +28 -10
- package/dist/core/pdf-engine.js.map +1 -1
- package/dist/core/performance-optimizer.d.ts +3 -0
- package/dist/core/performance-optimizer.d.ts.map +1 -1
- package/dist/core/performance-optimizer.js +17 -4
- package/dist/core/performance-optimizer.js.map +1 -1
- package/dist/core/unified-layer-builder.d.ts +8 -2
- package/dist/core/unified-layer-builder.d.ts.map +1 -1
- package/dist/core/unified-layer-builder.js +58 -22
- package/dist/core/unified-layer-builder.js.map +1 -1
- package/dist/index.d.ts +5 -2
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +3 -1
- package/dist/index.js.map +1 -1
- package/dist/types.d.ts +22 -0
- package/dist/types.d.ts.map +1 -1
- package/dist/types.js +6 -0
- package/dist/types.js.map +1 -1
- package/dist/utils/pdf-rotation-math.d.ts +11 -0
- package/dist/utils/pdf-rotation-math.d.ts.map +1 -0
- package/dist/utils/pdf-rotation-math.js +16 -0
- package/dist/utils/pdf-rotation-math.js.map +1 -0
- package/dist/utils/rotate-bbox.d.ts +20 -0
- package/dist/utils/rotate-bbox.d.ts.map +1 -0
- package/dist/utils/rotate-bbox.js +101 -0
- package/dist/utils/rotate-bbox.js.map +1 -0
- package/package.json +4 -4
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import { PDFHighlightViewer as IPDFHighlightViewer } from './api';
|
|
2
|
-
import { PDFSource, ViewerOptions, LoadPDFOptions, TextRange, SelectionWithMetadata, PerformanceMetrics, HighlightAnalytics, AccessibilityFeatures, InteractionMode, InputHighlightData, HighlightStyle, HighlightLabelStyle, ZoomValue, ThumbnailOptions } from './types';
|
|
2
|
+
import { PDFSource, ViewerOptions, LoadPDFOptions, TextRange, SelectionWithMetadata, PerformanceMetrics, HighlightAnalytics, AccessibilityFeatures, InteractionMode, InputHighlightData, HighlightStyle, HighlightLabelStyle, ZoomValue, ThumbnailOptions, PageRotationDegrees, RotationDirection } from './types';
|
|
3
3
|
type EventCallback = (data?: unknown) => void;
|
|
4
4
|
export declare class PDFHighlightViewer implements IPDFHighlightViewer {
|
|
5
5
|
private pdfEngine;
|
|
@@ -23,12 +23,17 @@ export declare class PDFHighlightViewer implements IPDFHighlightViewer {
|
|
|
23
23
|
private isInitialized;
|
|
24
24
|
private navIndex;
|
|
25
25
|
private pageDimensions;
|
|
26
|
+
/** Intrinsic page size in normalized units (PDF default viewport at currentScale / scale). */
|
|
27
|
+
private intrinsicPageNormalized;
|
|
28
|
+
/** Extra clockwise rotation per page on top of PDF `/Rotate`. */
|
|
29
|
+
private pageDisplayRotations;
|
|
26
30
|
private defaultPageHeight;
|
|
27
31
|
private eventListeners;
|
|
28
32
|
private scrollListener;
|
|
29
33
|
private analytics;
|
|
30
34
|
constructor();
|
|
31
35
|
init(container: HTMLElement, options?: ViewerOptions): Promise<void>;
|
|
36
|
+
private syncPageDisplayRotationsFromOptions;
|
|
32
37
|
/**
|
|
33
38
|
* Setup container with proper structure and styling
|
|
34
39
|
*/
|
|
@@ -50,8 +55,11 @@ export declare class PDFHighlightViewer implements IPDFHighlightViewer {
|
|
|
50
55
|
* Set placeholder size for a page container using real PDF dimensions
|
|
51
56
|
*/
|
|
52
57
|
private setPagePlaceholderSize;
|
|
58
|
+
private getUserClockwiseRotation;
|
|
59
|
+
private effectiveViewportRotationDegrees;
|
|
53
60
|
/**
|
|
54
|
-
* Get and cache
|
|
61
|
+
* Get and cache display page dimensions (rotated viewport pixels at currentScale)
|
|
62
|
+
* and intrinsic normalized size for highlight mapping.
|
|
55
63
|
*/
|
|
56
64
|
private getPageDimensions;
|
|
57
65
|
/**
|
|
@@ -95,6 +103,8 @@ export declare class PDFHighlightViewer implements IPDFHighlightViewer {
|
|
|
95
103
|
resetZoom(): void;
|
|
96
104
|
getCurrentPage(): number;
|
|
97
105
|
getTotalPages(): number;
|
|
106
|
+
setPageDisplayRotation(pageNumber: number, degrees: PageRotationDegrees, direction?: RotationDirection): void;
|
|
107
|
+
getPageDisplayRotation(pageNumber: number): PageRotationDegrees;
|
|
98
108
|
getThumbnails(pageNumbers: number[], options?: ThumbnailOptions): Promise<Map<number, HTMLCanvasElement>>;
|
|
99
109
|
getThumbnailsDataUrl(pageNumbers: number[], options?: ThumbnailOptions): Promise<Map<number, string>>;
|
|
100
110
|
/**
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"PDFHighlightViewer.d.ts","sourceRoot":"","sources":["../src/PDFHighlightViewer.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,kBAAkB,IAAI,mBAAmB,EAAE,MAAM,OAAO,CAAC;AAClE,OAAO,EACL,SAAS,EACT,aAAa,EACb,cAAc,EAKd,SAAS,EACT,qBAAqB,EACrB,kBAAkB,EAClB,kBAAkB,EAClB,qBAAqB,EACrB,eAAe,EACf,kBAAkB,EAElB,cAAc,EACd,mBAAmB,EACnB,SAAS,EAET,gBAAgB,
|
|
1
|
+
{"version":3,"file":"PDFHighlightViewer.d.ts","sourceRoot":"","sources":["../src/PDFHighlightViewer.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,kBAAkB,IAAI,mBAAmB,EAAE,MAAM,OAAO,CAAC;AAClE,OAAO,EACL,SAAS,EACT,aAAa,EACb,cAAc,EAKd,SAAS,EACT,qBAAqB,EACrB,kBAAkB,EAClB,kBAAkB,EAClB,qBAAqB,EACrB,eAAe,EACf,kBAAkB,EAElB,cAAc,EACd,mBAAmB,EACnB,SAAS,EAET,gBAAgB,EAChB,mBAAmB,EACnB,iBAAiB,EAClB,MAAM,SAAS,CAAC;AA6BjB,KAAK,aAAa,GAAG,CAAC,IAAI,CAAC,EAAE,OAAO,KAAK,IAAI,CAAC;AAE9C,qBAAa,kBAAmB,YAAW,mBAAmB;IAC5D,OAAO,CAAC,SAAS,CAAY;IAC7B,OAAO,CAAC,eAAe,CAAkB;IACzC,OAAO,CAAC,YAAY,CAAsB;IAC1C,OAAO,CAAC,kBAAkB,CAA4B;IACtD,OAAO,CAAC,oBAAoB,CAAuB;IAEnD,OAAO,CAAC,SAAS,CAA4B;IAC7C,OAAO,CAAC,YAAY,CAA4B;IAChD,OAAO,CAAC,cAAc,CAAkC;IAExD,OAAO,CAAC,OAAO,CAAgB;IAC/B,OAAO,CAAC,eAAe,CAKrB;IACF,OAAO,CAAC,WAAW,CAAK;IACxB,OAAO,CAAC,YAAY,CAAO;IAC3B,OAAO,CAAC,UAAU,CAAK;IACvB,sEAAsE;IACtE,OAAO,CAAC,gBAAgB,CAAK;IAC7B,8EAA8E;IAC9E,OAAO,CAAC,aAAa,CAAyB;IAC9C,OAAO,CAAC,cAAc,CAAuB;IAC7C,OAAO,CAAC,aAAa,CAAS;IAE9B,OAAO,CAAC,QAAQ,CAAM;IAEtB,OAAO,CAAC,cAAc,CAAwD;IAC9E,8FAA8F;IAC9F,OAAO,CAAC,uBAAuB,CAAwD;IACvF,iEAAiE;IACjE,OAAO,CAAC,oBAAoB,CAA0C;IACtE,OAAO,CAAC,iBAAiB,CAAO;IAEhC,OAAO,CAAC,cAAc,CAAoD;IAC1E,OAAO,CAAC,cAAc,CAA6B;IACnD,OAAO,CAAC,SAAS,CAKf;;IAyCI,IAAI,CAAC,SAAS,EAAE,WAAW,EAAE,OAAO,CAAC,EAAE,aAAa,GAAG,OAAO,CAAC,IAAI,CAAC;IAkC1E,OAAO,CAAC,mCAAmC;IAY3C;;OAEG;IACH,OAAO,CAAC,cAAc;IAgBtB;;OAEG;IACH,OAAO,CAAC,OAAO;IAuHf;;OAEG;IACH,OAAO,CAAC,mBAAmB;IAuB3B,OAAO,CAAC,gBAAgB;IAMxB;;OAEG;IACH,OAAO,CAAC,YAAY;IA8DpB;;OAEG;IACH,OAAO,CAAC,sBAAsB;IAW9B,OAAO,CAAC,wBAAwB;IAIhC,OAAO,CAAC,gCAAgC;IAUxC;;;OAGG;YACW,iBAAiB;IA6B/B;;OAEG;IACH,OAAO,CAAC,kBAAkB;IAY1B;;OAEG;IACH,OAAO,CAAC,wBAAwB;IA0C1B,OAAO,CAAC,MAAM,EAAE,SAAS,EAAE,OAAO,CAAC,EAAE,cAAc,GAAG,OAAO,CAAC,IAAI,CAAC;IAwCzE;;OAEG;IACH,OAAO,CAAC,sBAAsB;IAa9B,8FAA8F;IAC9F,OAAO,CAAC,oBAAoB;IAW5B;;OAEG;YACW,oBAAoB;IA8BlC;;OAEG;YACW,gBAAgB;YAwBhB,qBAAqB;IAoBnC;;OAEG;YACW,UAAU;IAqDxB,YAAY,CAAC,WAAW,EAAE,MAAM,EAAE,GAAG,OAAO,CAAC,IAAI,CAAC;IAMlD,OAAO,CAAC,UAAU,EAAE,MAAM,GAAG,IAAI;IASjC,OAAO,IAAI,MAAM;IAIjB,OAAO,CAAC,KAAK,EAAE,SAAS,GAAG,IAAI;IAU/B,OAAO,CAAC,SAAS;YAUH,WAAW;YAKX,cAAc;YAKd,gBAAgB;IAa9B,MAAM,IAAI,IAAI;IAId,OAAO,IAAI,IAAI;IAIf,SAAS,IAAI,IAAI;IAIjB,cAAc,IAAI,MAAM;IAIxB,aAAa,IAAI,MAAM;IAIvB,sBAAsB,CACpB,UAAU,EAAE,MAAM,EAClB,OAAO,EAAE,mBAAmB,EAC5B,SAAS,GAAE,iBAA+C,GACzD,IAAI;IAqBP,sBAAsB,CAAC,UAAU,EAAE,MAAM,GAAG,mBAAmB;IAIzD,aAAa,CACjB,WAAW,EAAE,MAAM,EAAE,EACrB,OAAO,CAAC,EAAE,gBAAgB,GACzB,OAAO,CAAC,GAAG,CAAC,MAAM,EAAE,iBAAiB,CAAC,CAAC;IAUpC,oBAAoB,CACxB,WAAW,EAAE,MAAM,EAAE,EACrB,OAAO,CAAC,EAAE,gBAAgB,GACzB,OAAO,CAAC,GAAG,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC;IAc/B;;OAEG;IACH,mBAAmB,IAAI,IAAI;IAe3B;;OAEG;IACH,oBAAoB,IAAI,IAAI;IAgB5B;;OAEG;IACH,mBAAmB,IAAI,OAAO;IAU9B;;OAEG;IACH,sBAAsB,IAAI,OAAO;IAQjC,cAAc,CAAC,IAAI,EAAE,kBAAkB,EAAE,GAAG,IAAI;IAchD,YAAY,CAAC,SAAS,EAAE,kBAAkB,GAAG,IAAI;IA4BjD,eAAe,CAAC,MAAM,EAAE,MAAM,GAAG,IAAI;IA4BrC,oBAAoB,CAClB,MAAM,EAAE,MAAM,EACd,UAAU,EAAE,OAAO,CAAC,cAAc,CAAC,EACnC,eAAe,CAAC,EAAE,OAAO,CAAC,mBAAmB,CAAC,GAC7C,IAAI;IAwCP;;OAEG;YACW,sBAAsB;IA+CpC;;OAEG;IACH,OAAO,CAAC,sBAAsB;IAmB9B;;OAEG;YACW,oBAAoB;IAiElC,aAAa;sBACC,IAAI;uBAIH,IAAI;4BAIC,MAAM;uCAKK,qBAAqB,GAAG,IAAI;8BAIrC,IAAI;6BAIH,SAAS,KAAG,IAAI;iCAIb,OAAO,GAAG,WAAW,GAAG,UAAU,KAAa,IAAI;+CAQpC,cAAc,KAAG,kBAAkB,GAAG,IAAI;MAuBjF;IAMF,OAAO,CAAC,iBAAiB;IAsCzB,aAAa,CAAC,MAAM,EAAE,MAAM,EAAE,eAAe,SAAI,GAAG,IAAI;IAuCxD,aAAa,IAAI,IAAI;IASrB,iBAAiB,IAAI,IAAI;IASzB,cAAc,CAAC,UAAU,EAAE,MAAM,EAAE,CAAC,EAAE,MAAM,EAAE,CAAC,EAAE,MAAM,GAAG,IAAI;IAwB9D,gBAAgB,CAAC,KAAK,EAAE,MAAM,GAAG,kBAAkB,EAAE;IAwBrD,kBAAkB,CAAC,IAAI,EAAE,eAAe,GAAG,IAAI;IAI/C,kBAAkB,IAAI,eAAe;IAQrC,qBAAqB,IAAI,kBAAkB;IAmB3C;;OAEG;IACH,cAAc,IAAI;QAChB,aAAa,EAAE,MAAM,CAAC;QACtB,UAAU,EAAE,MAAM,CAAC;QACnB,iBAAiB,EAAE,MAAM,CAAC;QAC1B,gBAAgB,EAAE,MAAM,CAAC;KAC1B;IAaD,YAAY,IAAI,kBAAkB;IAIlC,eAAe,IAAI,IAAI;IAIvB,gBAAgB,IAAI,IAAI;IAQxB,aAAa,EAAE,qBAAqB,CAgClC;IAMF,gBAAgB,CAAC,KAAK,EAAE,MAAM,EAAE,QAAQ,EAAE,aAAa,GAAG,IAAI;IAI9D,mBAAmB,CAAC,KAAK,EAAE,MAAM,EAAE,QAAQ,EAAE,aAAa,GAAG,IAAI;IASjE,IAAI,CAAC,KAAK,EAAE,MAAM,EAAE,IAAI,CAAC,EAAE,OAAO,GAAG,IAAI;IAgBzC,aAAa,CAAC,MAAM,GAAE,KAAK,GAAG,MAAc,EAAE,OAAO,SAAM,GAAG,OAAO,CAAC,IAAI,CAAC;IAyB3E,WAAW;;;;;;;;;;;IAcX,OAAO,IAAI,IAAI;IAWf,OAAO,CAAC,4BAA4B;IAapC;;OAEG;YACW,mBAAmB;IAsOjC,OAAO,CAAC,gBAAgB;IAUxB,OAAO,CAAC,iBAAiB;IAIzB,OAAO,CAAC,eAAe;IAOvB,OAAO,CAAC,gBAAgB;IAMxB,OAAO,CAAC,oBAAoB;IAQ5B;;SAEK;IACL,sBAAsB,CAAC,UAAU,EAAE,MAAM,EAAE,UAAU,CAAC,EAAE,MAAM,EAAE;IA0FhE;;OAEG;IACH,OAAO,CAAC,wBAAwB;IAoBhC,OAAO,CAAC,0BAA0B;IAWlC,OAAO,CAAC,oBAAoB;IA2D5B;;OAEG;IACH,OAAO,CAAC,sBAAsB;IAM9B;;;;;;;;;;OAUG;IACH,OAAO,CAAC,wBAAwB;IAKhC;;;;;;;OAOG;IACH,OAAO,CAAC,eAAe;IASvB;;OAEG;IACH,qBAAqB,CAAC,MAAM,EAAE,MAAM,GAAG,IAAI;IA4C3C;;OAEG;IACH,6BAA6B,CAAC,oBAAoB,UAAO,GAAG,IAAI;IA8ChE;;OAEG;YACW,kBAAkB;IA0IhC;;OAEG;IACH,OAAO,CAAC,0BAA0B;IAwClC;;OAEG;IACH,OAAO,CAAC,oBAAoB;IAmD5B,OAAO,IAAI,IAAI;CAyBhB;AAED,eAAe,kBAAkB,CAAC"}
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { ZoomMode, } from './types';
|
|
1
|
+
import { ZoomMode, RotationDirection, } from './types';
|
|
2
2
|
import { PDFEngine } from './core/pdf-engine';
|
|
3
3
|
import { ViewportManager } from './core/viewport-manager';
|
|
4
4
|
import { UnifiedLayerBuilder } from './core/unified-layer-builder';
|
|
@@ -7,6 +7,8 @@ import { PerformanceOptimizer } from './core/performance-optimizer';
|
|
|
7
7
|
import { buildHighlightsIndex } from './utils/highlight-adapter';
|
|
8
8
|
import { applyHighlightVisualStyle, getHighlightBaseOpacity, getHighlightHoverOpacity, resolveHighlightStyle, } from './utils/highlight-style';
|
|
9
9
|
import { appendLabelIcon, applyBaseOutlineStyle, applyLabelOutlineStyle, applyLabelStyle, scaleLabelStyle, } from './utils/label-style';
|
|
10
|
+
import { clockwiseToCcw, displayRotationToClockwise, rotateBoundingBoxForCcwRotation, } from './utils/rotate-bbox';
|
|
11
|
+
import { sumPdfIntrinsicAndUserRotation } from './utils/pdf-rotation-math';
|
|
10
12
|
const CONTAINER_PADDING = 40;
|
|
11
13
|
const ZOOM_STEP = 1.2;
|
|
12
14
|
export class PDFHighlightViewer {
|
|
@@ -31,6 +33,10 @@ export class PDFHighlightViewer {
|
|
|
31
33
|
this.isInitialized = false;
|
|
32
34
|
this.navIndex = -1;
|
|
33
35
|
this.pageDimensions = new Map();
|
|
36
|
+
/** Intrinsic page size in normalized units (PDF default viewport at currentScale / scale). */
|
|
37
|
+
this.intrinsicPageNormalized = new Map();
|
|
38
|
+
/** Extra clockwise rotation per page on top of PDF `/Rotate`. */
|
|
39
|
+
this.pageDisplayRotations = new Map();
|
|
34
40
|
this.defaultPageHeight = 800;
|
|
35
41
|
this.eventListeners = [];
|
|
36
42
|
this.scrollListener = null;
|
|
@@ -174,9 +180,22 @@ export class PDFHighlightViewer {
|
|
|
174
180
|
if (this.options.accessibility) {
|
|
175
181
|
this.setupAccessibility();
|
|
176
182
|
}
|
|
183
|
+
this.syncPageDisplayRotationsFromOptions();
|
|
177
184
|
this.isInitialized = true;
|
|
178
185
|
this.emit('initialized');
|
|
179
186
|
}
|
|
187
|
+
syncPageDisplayRotationsFromOptions() {
|
|
188
|
+
this.pageDisplayRotations.clear();
|
|
189
|
+
const raw = this.options.pageDisplayRotations;
|
|
190
|
+
if (!raw)
|
|
191
|
+
return;
|
|
192
|
+
for (const [key, value] of Object.entries(raw)) {
|
|
193
|
+
const n = Number(key);
|
|
194
|
+
if (Number.isInteger(n) && n >= 1) {
|
|
195
|
+
this.pageDisplayRotations.set(n, value);
|
|
196
|
+
}
|
|
197
|
+
}
|
|
198
|
+
}
|
|
180
199
|
/**
|
|
181
200
|
* Setup container with proper structure and styling
|
|
182
201
|
*/
|
|
@@ -304,6 +323,12 @@ export class PDFHighlightViewer {
|
|
|
304
323
|
z-index: 10;
|
|
305
324
|
}
|
|
306
325
|
|
|
326
|
+
.highlight-label {
|
|
327
|
+
max-width: 150px;
|
|
328
|
+
white-space: normal;
|
|
329
|
+
word-break: break-word;
|
|
330
|
+
flex-shrink: 1;
|
|
331
|
+
}
|
|
307
332
|
`;
|
|
308
333
|
document.head.appendChild(style);
|
|
309
334
|
}
|
|
@@ -408,22 +433,38 @@ export class PDFHighlightViewer {
|
|
|
408
433
|
pageContainer.style.height = `${this.defaultPageHeight}px`;
|
|
409
434
|
}
|
|
410
435
|
}
|
|
436
|
+
getUserClockwiseRotation(pageNumber) {
|
|
437
|
+
return this.pageDisplayRotations.get(pageNumber) ?? 0;
|
|
438
|
+
}
|
|
439
|
+
effectiveViewportRotationDegrees(intrinsicRotateDegrees, pageNumber) {
|
|
440
|
+
return sumPdfIntrinsicAndUserRotation(intrinsicRotateDegrees, this.getUserClockwiseRotation(pageNumber));
|
|
441
|
+
}
|
|
411
442
|
/**
|
|
412
|
-
* Get and cache
|
|
443
|
+
* Get and cache display page dimensions (rotated viewport pixels at currentScale)
|
|
444
|
+
* and intrinsic normalized size for highlight mapping.
|
|
413
445
|
*/
|
|
414
446
|
async getPageDimensions(pageNumber) {
|
|
415
|
-
|
|
416
|
-
const
|
|
417
|
-
if (
|
|
418
|
-
return
|
|
419
|
-
|
|
420
|
-
const
|
|
421
|
-
const
|
|
447
|
+
const cachedDisplay = this.pageDimensions.get(pageNumber);
|
|
448
|
+
const cachedIntrinsic = this.intrinsicPageNormalized.get(pageNumber);
|
|
449
|
+
if (cachedDisplay && cachedIntrinsic) {
|
|
450
|
+
return cachedDisplay;
|
|
451
|
+
}
|
|
452
|
+
const pdfPage = await this.pdfEngine.getPage(pageNumber);
|
|
453
|
+
const intrinsicVp = pdfPage.getViewport({ scale: this.currentScale });
|
|
454
|
+
const scale = this.currentScale > 0 ? this.currentScale : 1;
|
|
455
|
+
this.intrinsicPageNormalized.set(pageNumber, {
|
|
456
|
+
width: intrinsicVp.width / scale,
|
|
457
|
+
height: intrinsicVp.height / scale,
|
|
458
|
+
});
|
|
459
|
+
const effectiveRotation = this.effectiveViewportRotationDegrees(pdfPage.rotate, pageNumber);
|
|
460
|
+
const displayVp = pdfPage.getViewport({
|
|
461
|
+
scale: this.currentScale,
|
|
462
|
+
rotation: effectiveRotation,
|
|
463
|
+
});
|
|
422
464
|
const dimensions = {
|
|
423
|
-
width:
|
|
424
|
-
height:
|
|
465
|
+
width: displayVp.width,
|
|
466
|
+
height: displayVp.height,
|
|
425
467
|
};
|
|
426
|
-
// Cache the dimensions
|
|
427
468
|
this.pageDimensions.set(pageNumber, dimensions);
|
|
428
469
|
return dimensions;
|
|
429
470
|
}
|
|
@@ -492,6 +533,7 @@ export class PDFHighlightViewer {
|
|
|
492
533
|
await this.pdfEngine.loadDocument(source);
|
|
493
534
|
const docInfo = this.pdfEngine.getDocumentInfo();
|
|
494
535
|
this.documentNumPages = docInfo.numPages;
|
|
536
|
+
this.syncPageDisplayRotationsFromOptions();
|
|
495
537
|
const rawSelected = options?.selectedPages ?? this.options.selectedPages;
|
|
496
538
|
const selectedPages = this.normalizeSelectedPages(rawSelected, this.documentNumPages);
|
|
497
539
|
this.selectedPages = selectedPages;
|
|
@@ -622,8 +664,10 @@ export class PDFHighlightViewer {
|
|
|
622
664
|
try {
|
|
623
665
|
// Add loading state
|
|
624
666
|
pageContainer.classList.add('loading');
|
|
667
|
+
const pdfPage = await this.pdfEngine.getPage(pageNumber);
|
|
668
|
+
const effectiveRotation = this.effectiveViewportRotationDegrees(pdfPage.rotate, pageNumber);
|
|
625
669
|
// Render PDF canvas
|
|
626
|
-
const canvas = await this.pdfEngine.renderPage(pageNumber, this.currentScale);
|
|
670
|
+
const canvas = await this.pdfEngine.renderPage(pageNumber, this.currentScale, undefined, effectiveRotation);
|
|
627
671
|
// Clear container and add canvas
|
|
628
672
|
pageContainer.innerHTML = '';
|
|
629
673
|
pageContainer.appendChild(canvas);
|
|
@@ -695,8 +739,10 @@ export class PDFHighlightViewer {
|
|
|
695
739
|
if (!this.container) {
|
|
696
740
|
return { scaleX: 1, scaleY: 1 };
|
|
697
741
|
}
|
|
698
|
-
const
|
|
699
|
-
const
|
|
742
|
+
const pageNum = this.currentPage || 1;
|
|
743
|
+
const page = await this.pdfEngine.getPage(pageNum);
|
|
744
|
+
const effectiveRotation = this.effectiveViewportRotationDegrees(page.rotate, pageNum);
|
|
745
|
+
const viewport = page.getViewport({ scale: 1, rotation: effectiveRotation });
|
|
700
746
|
const scaleX = (this.container.clientWidth - CONTAINER_PADDING) / viewport.width;
|
|
701
747
|
const scaleY = (this.container.clientHeight - CONTAINER_PADDING) / viewport.height;
|
|
702
748
|
return { scaleX, scaleY };
|
|
@@ -716,8 +762,38 @@ export class PDFHighlightViewer {
|
|
|
716
762
|
getTotalPages() {
|
|
717
763
|
return this.totalPages;
|
|
718
764
|
}
|
|
765
|
+
setPageDisplayRotation(pageNumber, degrees, direction = RotationDirection.Clockwise) {
|
|
766
|
+
if (degrees === 0) {
|
|
767
|
+
this.pageDisplayRotations.delete(pageNumber);
|
|
768
|
+
if (this.options.pageDisplayRotations) {
|
|
769
|
+
const next = { ...this.options.pageDisplayRotations };
|
|
770
|
+
delete next[pageNumber];
|
|
771
|
+
this.options.pageDisplayRotations = Object.keys(next).length > 0 ? next : undefined;
|
|
772
|
+
}
|
|
773
|
+
}
|
|
774
|
+
else {
|
|
775
|
+
const cw = displayRotationToClockwise(degrees, direction);
|
|
776
|
+
this.pageDisplayRotations.set(pageNumber, cw);
|
|
777
|
+
this.options.pageDisplayRotations = {
|
|
778
|
+
...(this.options.pageDisplayRotations ?? {}),
|
|
779
|
+
[pageNumber]: cw,
|
|
780
|
+
};
|
|
781
|
+
}
|
|
782
|
+
void this.reRenderVisiblePages();
|
|
783
|
+
this.emit('pageRotationChanged', { pageNumber, degrees, direction });
|
|
784
|
+
}
|
|
785
|
+
getPageDisplayRotation(pageNumber) {
|
|
786
|
+
return this.pageDisplayRotations.get(pageNumber) ?? 0;
|
|
787
|
+
}
|
|
719
788
|
async getThumbnails(pageNumbers, options) {
|
|
720
|
-
|
|
789
|
+
const viewportRotations = { ...(options?.viewportRotations ?? {}) };
|
|
790
|
+
for (const n of pageNumbers) {
|
|
791
|
+
if (viewportRotations[n] !== undefined)
|
|
792
|
+
continue;
|
|
793
|
+
const pdfPage = await this.pdfEngine.getPage(n);
|
|
794
|
+
viewportRotations[n] = this.effectiveViewportRotationDegrees(pdfPage.rotate, n);
|
|
795
|
+
}
|
|
796
|
+
return this.pdfEngine.getThumbnails(pageNumbers, { ...options, viewportRotations });
|
|
721
797
|
}
|
|
722
798
|
async getThumbnailsDataUrl(pageNumbers, options) {
|
|
723
799
|
const canvases = await this.getThumbnails(pageNumbers, options);
|
|
@@ -811,7 +887,7 @@ export class PDFHighlightViewer {
|
|
|
811
887
|
// Refresh only affected pages
|
|
812
888
|
for (const pageNumber of affectedPages) {
|
|
813
889
|
this.refreshHighlightLayerForPage(pageNumber);
|
|
814
|
-
this.updatePageUnifiedLayer(pageNumber);
|
|
890
|
+
void this.updatePageUnifiedLayer(pageNumber);
|
|
815
891
|
this.buildSpatialIndexForPage(pageNumber);
|
|
816
892
|
}
|
|
817
893
|
this.emit('highlightAdded', { highlight, pages: Array.from(affectedPages) });
|
|
@@ -833,7 +909,7 @@ export class PDFHighlightViewer {
|
|
|
833
909
|
this.updateAnalytics();
|
|
834
910
|
for (const pageNumber of affectedPages) {
|
|
835
911
|
this.refreshHighlightLayerForPage(pageNumber);
|
|
836
|
-
this.updatePageUnifiedLayer(pageNumber);
|
|
912
|
+
void this.updatePageUnifiedLayer(pageNumber);
|
|
837
913
|
this.buildSpatialIndexForPage(pageNumber);
|
|
838
914
|
}
|
|
839
915
|
this.emit('highlightRemoved', { termId, pages: Array.from(affectedPages) });
|
|
@@ -866,7 +942,7 @@ export class PDFHighlightViewer {
|
|
|
866
942
|
this.updateAnalytics();
|
|
867
943
|
for (const pageNumber of affectedPages) {
|
|
868
944
|
this.refreshHighlightLayerForPage(pageNumber);
|
|
869
|
-
this.updatePageUnifiedLayer(pageNumber);
|
|
945
|
+
void this.updatePageUnifiedLayer(pageNumber);
|
|
870
946
|
this.buildSpatialIndexForPage(pageNumber);
|
|
871
947
|
}
|
|
872
948
|
this.emit('styleUpdated', { termId, style: next.style, patch: stylePatch });
|
|
@@ -874,7 +950,7 @@ export class PDFHighlightViewer {
|
|
|
874
950
|
/**
|
|
875
951
|
* Update unified layer for a specific page
|
|
876
952
|
*/
|
|
877
|
-
updatePageUnifiedLayer(pageNumber) {
|
|
953
|
+
async updatePageUnifiedLayer(pageNumber) {
|
|
878
954
|
const pageContainer = this.pageContainers.get(pageNumber);
|
|
879
955
|
if (!pageContainer)
|
|
880
956
|
return;
|
|
@@ -894,7 +970,19 @@ export class PDFHighlightViewer {
|
|
|
894
970
|
};
|
|
895
971
|
}),
|
|
896
972
|
}));
|
|
897
|
-
|
|
973
|
+
let viewport;
|
|
974
|
+
try {
|
|
975
|
+
const pdfPage = await this.pdfEngine.getPage(pageNumber);
|
|
976
|
+
const effectiveRotation = this.effectiveViewportRotationDegrees(pdfPage.rotate, pageNumber);
|
|
977
|
+
viewport = pdfPage.getViewport({
|
|
978
|
+
scale: this.currentScale,
|
|
979
|
+
rotation: effectiveRotation,
|
|
980
|
+
});
|
|
981
|
+
}
|
|
982
|
+
catch {
|
|
983
|
+
viewport = undefined;
|
|
984
|
+
}
|
|
985
|
+
this.layerBuilder.updateHighlights(pageContainer, normalizedHighlights, pageNumber, pageData.textContent, this.currentScale, viewport);
|
|
898
986
|
}
|
|
899
987
|
/**
|
|
900
988
|
* Update all unified layers
|
|
@@ -925,7 +1013,8 @@ export class PDFHighlightViewer {
|
|
|
925
1013
|
const pageToKeep = this.currentPage;
|
|
926
1014
|
// Clear ALL cached data for the new scale
|
|
927
1015
|
this.pdfEngine.clearAllPageCache();
|
|
928
|
-
this.pageDimensions.clear();
|
|
1016
|
+
this.pageDimensions.clear();
|
|
1017
|
+
this.intrinsicPageNormalized.clear();
|
|
929
1018
|
// Clear all containers and update their sizes for new scale
|
|
930
1019
|
let totalHeight = 0;
|
|
931
1020
|
let validDimensions = 0;
|
|
@@ -1036,14 +1125,8 @@ export class PDFHighlightViewer {
|
|
|
1036
1125
|
if (!this.container)
|
|
1037
1126
|
return;
|
|
1038
1127
|
const pageTop = this.getPageScrollTop(pageNumber);
|
|
1039
|
-
const
|
|
1040
|
-
const
|
|
1041
|
-
if (!pixelDimensions) {
|
|
1042
|
-
throw new Error(`Page dimensions for page ${pageNumber} are not available`);
|
|
1043
|
-
}
|
|
1044
|
-
const dimensions = this.toPageCoordinateDimensions(pixelDimensions);
|
|
1045
|
-
const normalizedY = origin.startsWith('bottom') ? dimensions.height - y : y;
|
|
1046
|
-
const targetY = pageTop + normalizedY * this.currentScale - this.container.clientHeight * 0.3;
|
|
1128
|
+
const normalizedBBox = this.normalizeBBoxForPage({ page: pageNumber, x1: x, y1: y, x2: x, y2: y }, pageNumber, this.options.bboxSourceDimensions, this.options.bboxOrigin);
|
|
1129
|
+
const targetY = pageTop + normalizedBBox.y1 * this.currentScale - this.container.clientHeight * 0.3;
|
|
1047
1130
|
this.container.scrollTop = Math.max(0, targetY);
|
|
1048
1131
|
this.emit('coordinateNavigation', { pageNumber, x, y });
|
|
1049
1132
|
}
|
|
@@ -1347,12 +1430,14 @@ export class PDFHighlightViewer {
|
|
|
1347
1430
|
labelEl.style.zIndex = '3';
|
|
1348
1431
|
labelEl.style.transform = 'translateX(-100%)';
|
|
1349
1432
|
labelEl.style.display = 'flex';
|
|
1350
|
-
labelEl.style.alignItems = '
|
|
1433
|
+
labelEl.style.alignItems = 'flex-start';
|
|
1351
1434
|
labelEl.style.justifyContent = 'flex-end';
|
|
1352
1435
|
labelEl.style.gap = highlight.isLabelScalable ? `${4 * scale}px` : '4px';
|
|
1353
1436
|
labelEl.style.pointerEvents = 'auto';
|
|
1354
1437
|
labelEl.style.cursor = 'pointer';
|
|
1355
|
-
labelEl.style.whiteSpace = '
|
|
1438
|
+
labelEl.style.whiteSpace = 'normal';
|
|
1439
|
+
labelEl.style.wordBreak = 'break-word';
|
|
1440
|
+
labelEl.style.maxWidth = `${left + labelOffsetLeft}px`;
|
|
1356
1441
|
if (effectiveLabelStyle?.borderColor !== undefined ||
|
|
1357
1442
|
effectiveLabelStyle?.borderWidth !== undefined) {
|
|
1358
1443
|
const borderColor = effectiveLabelStyle?.borderColor ?? 'currentColor';
|
|
@@ -1364,7 +1449,10 @@ export class PDFHighlightViewer {
|
|
|
1364
1449
|
labelEl.style.opacity = String(effectiveOpacity);
|
|
1365
1450
|
appendLabelIcon(labelEl, highlight.beforeIcon, effectiveLabelStyle);
|
|
1366
1451
|
if (highlight.label) {
|
|
1367
|
-
|
|
1452
|
+
const textSpan = document.createElement('span');
|
|
1453
|
+
textSpan.style.minWidth = '0';
|
|
1454
|
+
textSpan.textContent = highlight.label;
|
|
1455
|
+
labelEl.appendChild(textSpan);
|
|
1368
1456
|
}
|
|
1369
1457
|
highlightLayer.appendChild(labelEl);
|
|
1370
1458
|
}
|
|
@@ -1509,11 +1597,12 @@ export class PDFHighlightViewer {
|
|
|
1509
1597
|
normalizeBBoxForPage(bbox, pageNumber, bboxSourceDimensions, bboxOrigin) {
|
|
1510
1598
|
const origin = bboxOrigin ?? this.options.bboxOrigin ?? 'bottom-right';
|
|
1511
1599
|
const computedSourceDimensions = bboxSourceDimensions ?? this.options.bboxSourceDimensions;
|
|
1512
|
-
const
|
|
1513
|
-
if (!
|
|
1600
|
+
const intrinsic = this.intrinsicPageNormalized.get(pageNumber);
|
|
1601
|
+
if (!intrinsic) {
|
|
1514
1602
|
throw new Error(`Page dimensions for page ${pageNumber} are not available`);
|
|
1515
1603
|
}
|
|
1516
|
-
const
|
|
1604
|
+
const pageWidth = intrinsic.width;
|
|
1605
|
+
const pageHeight = intrinsic.height;
|
|
1517
1606
|
let x1 = bbox.x1;
|
|
1518
1607
|
let x2 = bbox.x2;
|
|
1519
1608
|
let y1 = bbox.y1;
|
|
@@ -1536,12 +1625,18 @@ export class PDFHighlightViewer {
|
|
|
1536
1625
|
y1 = pageHeight - y1;
|
|
1537
1626
|
y2 = pageHeight - y2;
|
|
1538
1627
|
}
|
|
1539
|
-
|
|
1628
|
+
let result = {
|
|
1540
1629
|
x1: Math.min(x1, x2),
|
|
1541
1630
|
y1: Math.min(y1, y2),
|
|
1542
1631
|
x2: Math.max(x1, x2),
|
|
1543
1632
|
y2: Math.max(y1, y2),
|
|
1544
1633
|
};
|
|
1634
|
+
const userCw = this.getUserClockwiseRotation(pageNumber);
|
|
1635
|
+
if (userCw !== 0) {
|
|
1636
|
+
const ccw = clockwiseToCcw(userCw);
|
|
1637
|
+
result = rotateBoundingBoxForCcwRotation(result, pageWidth, pageHeight, ccw);
|
|
1638
|
+
}
|
|
1639
|
+
return result;
|
|
1545
1640
|
}
|
|
1546
1641
|
/**
|
|
1547
1642
|
* Build spatial indices for displayed pages only
|
|
@@ -1676,9 +1771,12 @@ export class PDFHighlightViewer {
|
|
|
1676
1771
|
return;
|
|
1677
1772
|
}
|
|
1678
1773
|
try {
|
|
1679
|
-
// Get the PDF page and its viewport
|
|
1680
1774
|
const pdfPage = await this.pdfEngine.getPage(pageNumber);
|
|
1681
|
-
const
|
|
1775
|
+
const effectiveRotation = this.effectiveViewportRotationDegrees(pdfPage.rotate, pageNumber);
|
|
1776
|
+
const viewport = pdfPage.getViewport({
|
|
1777
|
+
scale: this.currentScale,
|
|
1778
|
+
rotation: effectiveRotation,
|
|
1779
|
+
});
|
|
1682
1780
|
// Extract text content from PDF
|
|
1683
1781
|
const textContent = await pdfPage.getTextContent();
|
|
1684
1782
|
// Create text layer container
|
|
@@ -1879,6 +1977,9 @@ export class PDFHighlightViewer {
|
|
|
1879
1977
|
// Clear state
|
|
1880
1978
|
this.eventListeners = [];
|
|
1881
1979
|
this.isInitialized = false;
|
|
1980
|
+
this.pageDimensions.clear();
|
|
1981
|
+
this.intrinsicPageNormalized.clear();
|
|
1982
|
+
this.pageDisplayRotations.clear();
|
|
1882
1983
|
this.emit('destroyed');
|
|
1883
1984
|
}
|
|
1884
1985
|
}
|