@epam/pdf-highlighter-kit 0.0.13 → 0.0.14
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 +126 -36
- 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":"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"}
|
|
@@ -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
|
*/
|
|
@@ -408,22 +427,38 @@ export class PDFHighlightViewer {
|
|
|
408
427
|
pageContainer.style.height = `${this.defaultPageHeight}px`;
|
|
409
428
|
}
|
|
410
429
|
}
|
|
430
|
+
getUserClockwiseRotation(pageNumber) {
|
|
431
|
+
return this.pageDisplayRotations.get(pageNumber) ?? 0;
|
|
432
|
+
}
|
|
433
|
+
effectiveViewportRotationDegrees(intrinsicRotateDegrees, pageNumber) {
|
|
434
|
+
return sumPdfIntrinsicAndUserRotation(intrinsicRotateDegrees, this.getUserClockwiseRotation(pageNumber));
|
|
435
|
+
}
|
|
411
436
|
/**
|
|
412
|
-
* Get and cache
|
|
437
|
+
* Get and cache display page dimensions (rotated viewport pixels at currentScale)
|
|
438
|
+
* and intrinsic normalized size for highlight mapping.
|
|
413
439
|
*/
|
|
414
440
|
async getPageDimensions(pageNumber) {
|
|
415
|
-
|
|
416
|
-
const
|
|
417
|
-
if (
|
|
418
|
-
return
|
|
419
|
-
|
|
420
|
-
const
|
|
421
|
-
const
|
|
441
|
+
const cachedDisplay = this.pageDimensions.get(pageNumber);
|
|
442
|
+
const cachedIntrinsic = this.intrinsicPageNormalized.get(pageNumber);
|
|
443
|
+
if (cachedDisplay && cachedIntrinsic) {
|
|
444
|
+
return cachedDisplay;
|
|
445
|
+
}
|
|
446
|
+
const pdfPage = await this.pdfEngine.getPage(pageNumber);
|
|
447
|
+
const intrinsicVp = pdfPage.getViewport({ scale: this.currentScale });
|
|
448
|
+
const scale = this.currentScale > 0 ? this.currentScale : 1;
|
|
449
|
+
this.intrinsicPageNormalized.set(pageNumber, {
|
|
450
|
+
width: intrinsicVp.width / scale,
|
|
451
|
+
height: intrinsicVp.height / scale,
|
|
452
|
+
});
|
|
453
|
+
const effectiveRotation = this.effectiveViewportRotationDegrees(pdfPage.rotate, pageNumber);
|
|
454
|
+
const displayVp = pdfPage.getViewport({
|
|
455
|
+
scale: this.currentScale,
|
|
456
|
+
rotation: effectiveRotation,
|
|
457
|
+
});
|
|
422
458
|
const dimensions = {
|
|
423
|
-
width:
|
|
424
|
-
height:
|
|
459
|
+
width: displayVp.width,
|
|
460
|
+
height: displayVp.height,
|
|
425
461
|
};
|
|
426
|
-
// Cache the dimensions
|
|
427
462
|
this.pageDimensions.set(pageNumber, dimensions);
|
|
428
463
|
return dimensions;
|
|
429
464
|
}
|
|
@@ -492,6 +527,7 @@ export class PDFHighlightViewer {
|
|
|
492
527
|
await this.pdfEngine.loadDocument(source);
|
|
493
528
|
const docInfo = this.pdfEngine.getDocumentInfo();
|
|
494
529
|
this.documentNumPages = docInfo.numPages;
|
|
530
|
+
this.syncPageDisplayRotationsFromOptions();
|
|
495
531
|
const rawSelected = options?.selectedPages ?? this.options.selectedPages;
|
|
496
532
|
const selectedPages = this.normalizeSelectedPages(rawSelected, this.documentNumPages);
|
|
497
533
|
this.selectedPages = selectedPages;
|
|
@@ -622,8 +658,10 @@ export class PDFHighlightViewer {
|
|
|
622
658
|
try {
|
|
623
659
|
// Add loading state
|
|
624
660
|
pageContainer.classList.add('loading');
|
|
661
|
+
const pdfPage = await this.pdfEngine.getPage(pageNumber);
|
|
662
|
+
const effectiveRotation = this.effectiveViewportRotationDegrees(pdfPage.rotate, pageNumber);
|
|
625
663
|
// Render PDF canvas
|
|
626
|
-
const canvas = await this.pdfEngine.renderPage(pageNumber, this.currentScale);
|
|
664
|
+
const canvas = await this.pdfEngine.renderPage(pageNumber, this.currentScale, undefined, effectiveRotation);
|
|
627
665
|
// Clear container and add canvas
|
|
628
666
|
pageContainer.innerHTML = '';
|
|
629
667
|
pageContainer.appendChild(canvas);
|
|
@@ -695,8 +733,10 @@ export class PDFHighlightViewer {
|
|
|
695
733
|
if (!this.container) {
|
|
696
734
|
return { scaleX: 1, scaleY: 1 };
|
|
697
735
|
}
|
|
698
|
-
const
|
|
699
|
-
const
|
|
736
|
+
const pageNum = this.currentPage || 1;
|
|
737
|
+
const page = await this.pdfEngine.getPage(pageNum);
|
|
738
|
+
const effectiveRotation = this.effectiveViewportRotationDegrees(page.rotate, pageNum);
|
|
739
|
+
const viewport = page.getViewport({ scale: 1, rotation: effectiveRotation });
|
|
700
740
|
const scaleX = (this.container.clientWidth - CONTAINER_PADDING) / viewport.width;
|
|
701
741
|
const scaleY = (this.container.clientHeight - CONTAINER_PADDING) / viewport.height;
|
|
702
742
|
return { scaleX, scaleY };
|
|
@@ -716,8 +756,38 @@ export class PDFHighlightViewer {
|
|
|
716
756
|
getTotalPages() {
|
|
717
757
|
return this.totalPages;
|
|
718
758
|
}
|
|
759
|
+
setPageDisplayRotation(pageNumber, degrees, direction = RotationDirection.Clockwise) {
|
|
760
|
+
if (degrees === 0) {
|
|
761
|
+
this.pageDisplayRotations.delete(pageNumber);
|
|
762
|
+
if (this.options.pageDisplayRotations) {
|
|
763
|
+
const next = { ...this.options.pageDisplayRotations };
|
|
764
|
+
delete next[pageNumber];
|
|
765
|
+
this.options.pageDisplayRotations = Object.keys(next).length > 0 ? next : undefined;
|
|
766
|
+
}
|
|
767
|
+
}
|
|
768
|
+
else {
|
|
769
|
+
const cw = displayRotationToClockwise(degrees, direction);
|
|
770
|
+
this.pageDisplayRotations.set(pageNumber, cw);
|
|
771
|
+
this.options.pageDisplayRotations = {
|
|
772
|
+
...(this.options.pageDisplayRotations ?? {}),
|
|
773
|
+
[pageNumber]: cw,
|
|
774
|
+
};
|
|
775
|
+
}
|
|
776
|
+
void this.reRenderVisiblePages();
|
|
777
|
+
this.emit('pageRotationChanged', { pageNumber, degrees, direction });
|
|
778
|
+
}
|
|
779
|
+
getPageDisplayRotation(pageNumber) {
|
|
780
|
+
return this.pageDisplayRotations.get(pageNumber) ?? 0;
|
|
781
|
+
}
|
|
719
782
|
async getThumbnails(pageNumbers, options) {
|
|
720
|
-
|
|
783
|
+
const viewportRotations = { ...(options?.viewportRotations ?? {}) };
|
|
784
|
+
for (const n of pageNumbers) {
|
|
785
|
+
if (viewportRotations[n] !== undefined)
|
|
786
|
+
continue;
|
|
787
|
+
const pdfPage = await this.pdfEngine.getPage(n);
|
|
788
|
+
viewportRotations[n] = this.effectiveViewportRotationDegrees(pdfPage.rotate, n);
|
|
789
|
+
}
|
|
790
|
+
return this.pdfEngine.getThumbnails(pageNumbers, { ...options, viewportRotations });
|
|
721
791
|
}
|
|
722
792
|
async getThumbnailsDataUrl(pageNumbers, options) {
|
|
723
793
|
const canvases = await this.getThumbnails(pageNumbers, options);
|
|
@@ -811,7 +881,7 @@ export class PDFHighlightViewer {
|
|
|
811
881
|
// Refresh only affected pages
|
|
812
882
|
for (const pageNumber of affectedPages) {
|
|
813
883
|
this.refreshHighlightLayerForPage(pageNumber);
|
|
814
|
-
this.updatePageUnifiedLayer(pageNumber);
|
|
884
|
+
void this.updatePageUnifiedLayer(pageNumber);
|
|
815
885
|
this.buildSpatialIndexForPage(pageNumber);
|
|
816
886
|
}
|
|
817
887
|
this.emit('highlightAdded', { highlight, pages: Array.from(affectedPages) });
|
|
@@ -833,7 +903,7 @@ export class PDFHighlightViewer {
|
|
|
833
903
|
this.updateAnalytics();
|
|
834
904
|
for (const pageNumber of affectedPages) {
|
|
835
905
|
this.refreshHighlightLayerForPage(pageNumber);
|
|
836
|
-
this.updatePageUnifiedLayer(pageNumber);
|
|
906
|
+
void this.updatePageUnifiedLayer(pageNumber);
|
|
837
907
|
this.buildSpatialIndexForPage(pageNumber);
|
|
838
908
|
}
|
|
839
909
|
this.emit('highlightRemoved', { termId, pages: Array.from(affectedPages) });
|
|
@@ -866,7 +936,7 @@ export class PDFHighlightViewer {
|
|
|
866
936
|
this.updateAnalytics();
|
|
867
937
|
for (const pageNumber of affectedPages) {
|
|
868
938
|
this.refreshHighlightLayerForPage(pageNumber);
|
|
869
|
-
this.updatePageUnifiedLayer(pageNumber);
|
|
939
|
+
void this.updatePageUnifiedLayer(pageNumber);
|
|
870
940
|
this.buildSpatialIndexForPage(pageNumber);
|
|
871
941
|
}
|
|
872
942
|
this.emit('styleUpdated', { termId, style: next.style, patch: stylePatch });
|
|
@@ -874,7 +944,7 @@ export class PDFHighlightViewer {
|
|
|
874
944
|
/**
|
|
875
945
|
* Update unified layer for a specific page
|
|
876
946
|
*/
|
|
877
|
-
updatePageUnifiedLayer(pageNumber) {
|
|
947
|
+
async updatePageUnifiedLayer(pageNumber) {
|
|
878
948
|
const pageContainer = this.pageContainers.get(pageNumber);
|
|
879
949
|
if (!pageContainer)
|
|
880
950
|
return;
|
|
@@ -894,7 +964,19 @@ export class PDFHighlightViewer {
|
|
|
894
964
|
};
|
|
895
965
|
}),
|
|
896
966
|
}));
|
|
897
|
-
|
|
967
|
+
let viewport;
|
|
968
|
+
try {
|
|
969
|
+
const pdfPage = await this.pdfEngine.getPage(pageNumber);
|
|
970
|
+
const effectiveRotation = this.effectiveViewportRotationDegrees(pdfPage.rotate, pageNumber);
|
|
971
|
+
viewport = pdfPage.getViewport({
|
|
972
|
+
scale: this.currentScale,
|
|
973
|
+
rotation: effectiveRotation,
|
|
974
|
+
});
|
|
975
|
+
}
|
|
976
|
+
catch {
|
|
977
|
+
viewport = undefined;
|
|
978
|
+
}
|
|
979
|
+
this.layerBuilder.updateHighlights(pageContainer, normalizedHighlights, pageNumber, pageData.textContent, this.currentScale, viewport);
|
|
898
980
|
}
|
|
899
981
|
/**
|
|
900
982
|
* Update all unified layers
|
|
@@ -925,7 +1007,8 @@ export class PDFHighlightViewer {
|
|
|
925
1007
|
const pageToKeep = this.currentPage;
|
|
926
1008
|
// Clear ALL cached data for the new scale
|
|
927
1009
|
this.pdfEngine.clearAllPageCache();
|
|
928
|
-
this.pageDimensions.clear();
|
|
1010
|
+
this.pageDimensions.clear();
|
|
1011
|
+
this.intrinsicPageNormalized.clear();
|
|
929
1012
|
// Clear all containers and update their sizes for new scale
|
|
930
1013
|
let totalHeight = 0;
|
|
931
1014
|
let validDimensions = 0;
|
|
@@ -1036,14 +1119,8 @@ export class PDFHighlightViewer {
|
|
|
1036
1119
|
if (!this.container)
|
|
1037
1120
|
return;
|
|
1038
1121
|
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;
|
|
1122
|
+
const normalizedBBox = this.normalizeBBoxForPage({ page: pageNumber, x1: x, y1: y, x2: x, y2: y }, pageNumber, this.options.bboxSourceDimensions, this.options.bboxOrigin);
|
|
1123
|
+
const targetY = pageTop + normalizedBBox.y1 * this.currentScale - this.container.clientHeight * 0.3;
|
|
1047
1124
|
this.container.scrollTop = Math.max(0, targetY);
|
|
1048
1125
|
this.emit('coordinateNavigation', { pageNumber, x, y });
|
|
1049
1126
|
}
|
|
@@ -1509,11 +1586,12 @@ export class PDFHighlightViewer {
|
|
|
1509
1586
|
normalizeBBoxForPage(bbox, pageNumber, bboxSourceDimensions, bboxOrigin) {
|
|
1510
1587
|
const origin = bboxOrigin ?? this.options.bboxOrigin ?? 'bottom-right';
|
|
1511
1588
|
const computedSourceDimensions = bboxSourceDimensions ?? this.options.bboxSourceDimensions;
|
|
1512
|
-
const
|
|
1513
|
-
if (!
|
|
1589
|
+
const intrinsic = this.intrinsicPageNormalized.get(pageNumber);
|
|
1590
|
+
if (!intrinsic) {
|
|
1514
1591
|
throw new Error(`Page dimensions for page ${pageNumber} are not available`);
|
|
1515
1592
|
}
|
|
1516
|
-
const
|
|
1593
|
+
const pageWidth = intrinsic.width;
|
|
1594
|
+
const pageHeight = intrinsic.height;
|
|
1517
1595
|
let x1 = bbox.x1;
|
|
1518
1596
|
let x2 = bbox.x2;
|
|
1519
1597
|
let y1 = bbox.y1;
|
|
@@ -1536,12 +1614,18 @@ export class PDFHighlightViewer {
|
|
|
1536
1614
|
y1 = pageHeight - y1;
|
|
1537
1615
|
y2 = pageHeight - y2;
|
|
1538
1616
|
}
|
|
1539
|
-
|
|
1617
|
+
let result = {
|
|
1540
1618
|
x1: Math.min(x1, x2),
|
|
1541
1619
|
y1: Math.min(y1, y2),
|
|
1542
1620
|
x2: Math.max(x1, x2),
|
|
1543
1621
|
y2: Math.max(y1, y2),
|
|
1544
1622
|
};
|
|
1623
|
+
const userCw = this.getUserClockwiseRotation(pageNumber);
|
|
1624
|
+
if (userCw !== 0) {
|
|
1625
|
+
const ccw = clockwiseToCcw(userCw);
|
|
1626
|
+
result = rotateBoundingBoxForCcwRotation(result, pageWidth, pageHeight, ccw);
|
|
1627
|
+
}
|
|
1628
|
+
return result;
|
|
1545
1629
|
}
|
|
1546
1630
|
/**
|
|
1547
1631
|
* Build spatial indices for displayed pages only
|
|
@@ -1676,9 +1760,12 @@ export class PDFHighlightViewer {
|
|
|
1676
1760
|
return;
|
|
1677
1761
|
}
|
|
1678
1762
|
try {
|
|
1679
|
-
// Get the PDF page and its viewport
|
|
1680
1763
|
const pdfPage = await this.pdfEngine.getPage(pageNumber);
|
|
1681
|
-
const
|
|
1764
|
+
const effectiveRotation = this.effectiveViewportRotationDegrees(pdfPage.rotate, pageNumber);
|
|
1765
|
+
const viewport = pdfPage.getViewport({
|
|
1766
|
+
scale: this.currentScale,
|
|
1767
|
+
rotation: effectiveRotation,
|
|
1768
|
+
});
|
|
1682
1769
|
// Extract text content from PDF
|
|
1683
1770
|
const textContent = await pdfPage.getTextContent();
|
|
1684
1771
|
// Create text layer container
|
|
@@ -1879,6 +1966,9 @@ export class PDFHighlightViewer {
|
|
|
1879
1966
|
// Clear state
|
|
1880
1967
|
this.eventListeners = [];
|
|
1881
1968
|
this.isInitialized = false;
|
|
1969
|
+
this.pageDimensions.clear();
|
|
1970
|
+
this.intrinsicPageNormalized.clear();
|
|
1971
|
+
this.pageDisplayRotations.clear();
|
|
1882
1972
|
this.emit('destroyed');
|
|
1883
1973
|
}
|
|
1884
1974
|
}
|