@syncfusion/ej2-pdf-data-extract 31.1.17 → 31.1.19
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/ej2-pdf-data-extract.umd.min.js +1 -1
- package/dist/global/ej2-pdf-data-extract.min.js +1 -1
- package/dist/global/index.d.ts +1 -1
- package/package.json +12 -44
- package/dist/ts/index.d.ts +0 -23
- package/dist/ts/index.ts +0 -23
- package/dist/ts/pdf-data-extract/core/content-parser-helper.d.ts +0 -62
- package/dist/ts/pdf-data-extract/core/content-parser-helper.ts +0 -661
- package/dist/ts/pdf-data-extract/core/enum.d.ts +0 -6
- package/dist/ts/pdf-data-extract/core/enum.ts +0 -6
- package/dist/ts/pdf-data-extract/core/graphic-state.d.ts +0 -33
- package/dist/ts/pdf-data-extract/core/graphic-state.ts +0 -106
- package/dist/ts/pdf-data-extract/core/pdf-data-extractor.d.ts +0 -210
- package/dist/ts/pdf-data-extract/core/pdf-data-extractor.ts +0 -998
- package/dist/ts/pdf-data-extract/core/pdf-text-parser.d.ts +0 -63
- package/dist/ts/pdf-data-extract/core/pdf-text-parser.ts +0 -498
- package/dist/ts/pdf-data-extract/core/redaction/index.d.ts +0 -7
- package/dist/ts/pdf-data-extract/core/redaction/index.ts +0 -7
- package/dist/ts/pdf-data-extract/core/redaction/pdf-path-segment.d.ts +0 -24
- package/dist/ts/pdf-data-extract/core/redaction/pdf-path-segment.ts +0 -59
- package/dist/ts/pdf-data-extract/core/redaction/pdf-redaction-processor.d.ts +0 -55
- package/dist/ts/pdf-data-extract/core/redaction/pdf-redaction-processor.ts +0 -590
- package/dist/ts/pdf-data-extract/core/redaction/pdf-redaction-region.d.ts +0 -281
- package/dist/ts/pdf-data-extract/core/redaction/pdf-redaction-region.ts +0 -342
- package/dist/ts/pdf-data-extract/core/redaction/pdf-redactor.d.ts +0 -172
- package/dist/ts/pdf-data-extract/core/redaction/pdf-redactor.ts +0 -414
- package/dist/ts/pdf-data-extract/core/redaction/pdf-shape-redaction.d.ts +0 -45
- package/dist/ts/pdf-data-extract/core/redaction/pdf-shape-redaction.ts +0 -281
- package/dist/ts/pdf-data-extract/core/redaction/shape-parser-helper.d.ts +0 -32
- package/dist/ts/pdf-data-extract/core/redaction/shape-parser-helper.ts +0 -479
- package/dist/ts/pdf-data-extract/core/redaction/text-glyph-mapper.d.ts +0 -12
- package/dist/ts/pdf-data-extract/core/redaction/text-glyph-mapper.ts +0 -153
- package/dist/ts/pdf-data-extract/core/text-extraction/binary-cmap-reader.d.ts +0 -24
- package/dist/ts/pdf-data-extract/core/text-extraction/binary-cmap-reader.ts +0 -281
- package/dist/ts/pdf-data-extract/core/text-extraction/cmap.d.ts +0 -50
- package/dist/ts/pdf-data-extract/core/text-extraction/cmap.ts +0 -565
- package/dist/ts/pdf-data-extract/core/text-extraction/compact-font-parser.d.ts +0 -191
- package/dist/ts/pdf-data-extract/core/text-extraction/compact-font-parser.ts +0 -1928
- package/dist/ts/pdf-data-extract/core/text-extraction/encoding-utils.d.ts +0 -102
- package/dist/ts/pdf-data-extract/core/text-extraction/encoding-utils.ts +0 -5780
- package/dist/ts/pdf-data-extract/core/text-extraction/font-structure.d.ts +0 -167
- package/dist/ts/pdf-data-extract/core/text-extraction/font-structure.ts +0 -1842
- package/dist/ts/pdf-data-extract/core/text-extraction/font-tables.d.ts +0 -5
- package/dist/ts/pdf-data-extract/core/text-extraction/font-tables.ts +0 -16
- package/dist/ts/pdf-data-extract/core/text-extraction/font-utils.d.ts +0 -18
- package/dist/ts/pdf-data-extract/core/text-extraction/font-utils.ts +0 -630
- package/dist/ts/pdf-data-extract/core/text-extraction/glyph.d.ts +0 -93
- package/dist/ts/pdf-data-extract/core/text-extraction/glyph.ts +0 -622
- package/dist/ts/pdf-data-extract/core/text-extraction/index.d.ts +0 -10
- package/dist/ts/pdf-data-extract/core/text-extraction/index.ts +0 -10
- package/dist/ts/pdf-data-extract/core/text-extraction/matrix-helper.d.ts +0 -38
- package/dist/ts/pdf-data-extract/core/text-extraction/matrix-helper.ts +0 -150
- package/dist/ts/pdf-data-extract/core/text-extraction/metrics.d.ts +0 -16
- package/dist/ts/pdf-data-extract/core/text-extraction/metrics.ts +0 -2938
- package/dist/ts/pdf-data-extract/core/text-structure.d.ts +0 -628
- package/dist/ts/pdf-data-extract/core/text-structure.ts +0 -668
- package/dist/ts/pdf-data-extract/core/utils.d.ts +0 -99
- package/dist/ts/pdf-data-extract/core/utils.ts +0 -626
- package/dist/ts/pdf-data-extract/index.d.ts +0 -23
- package/dist/ts/pdf-data-extract/index.ts +0 -23
|
@@ -1,479 +0,0 @@
|
|
|
1
|
-
import { _PdfContentStream, _PdfRecord, PdfPage, Point, Rectangle } from '@syncfusion/ej2-pdf';
|
|
2
|
-
import { _PdfPolygon } from './pdf-shape-redaction';
|
|
3
|
-
import { _TextProcessingMode } from '../enum';
|
|
4
|
-
import { _PdfBezierSegment, _PdfLineSegment, _PdfPathFigure } from './pdf-path-segment';
|
|
5
|
-
import { PdfRedactor } from './pdf-redactor';
|
|
6
|
-
import { PdfRedactionRegion } from './pdf-redaction-region';
|
|
7
|
-
|
|
8
|
-
export class _PdfShapeParser {
|
|
9
|
-
private _currentLocation: number[];
|
|
10
|
-
private _pathAccumulator: _PdfPathCommand[] = [];
|
|
11
|
-
private _clearPathAccumulator(): void {
|
|
12
|
-
this._pathAccumulator = [];
|
|
13
|
-
}
|
|
14
|
-
_findRedactPath(
|
|
15
|
-
recordCollection: _PdfRecord[],
|
|
16
|
-
i: number,
|
|
17
|
-
page: PdfPage,
|
|
18
|
-
redaction: PdfRedactor,
|
|
19
|
-
mode: _TextProcessingMode,
|
|
20
|
-
stream: _PdfContentStream
|
|
21
|
-
): number {
|
|
22
|
-
let startCount: number = 1;
|
|
23
|
-
let _currentPath: _PdfPathFigure;
|
|
24
|
-
let bezierSegment: _PdfBezierSegment;
|
|
25
|
-
for (let k: number = i; k < recordCollection.length; k++) {
|
|
26
|
-
const record: _PdfRecord = recordCollection[<number>k];
|
|
27
|
-
const value: string = record._operator.trim();
|
|
28
|
-
const element: string[] = record._operands;
|
|
29
|
-
if (
|
|
30
|
-
value === _PdfPathCommands.drawStroke || value === _PdfPathCommands.drawCloseStroke ||
|
|
31
|
-
value === _PdfPathCommands.fill || value === _PdfPathCommands.fillEvenOdd ||
|
|
32
|
-
value === _PdfPathCommands.fillStroke || value === _PdfPathCommands.fillEvenOddStroke ||
|
|
33
|
-
value === _PdfPathCommands.fillCloseStroke || value === _PdfPathCommands.fillEvenOddCloseStroke
|
|
34
|
-
) {
|
|
35
|
-
if (mode !== _TextProcessingMode.redaction) {
|
|
36
|
-
this._clearPathAccumulator();
|
|
37
|
-
return -1;
|
|
38
|
-
}
|
|
39
|
-
let shapePaths: _PdfPathCommand[] = this._getGeometry(_currentPath);
|
|
40
|
-
shapePaths = this._flattenIfNeeded(shapePaths);
|
|
41
|
-
const fullPath: { commands: _PdfPathCommand[],
|
|
42
|
-
renderingMode: _PdfPathCommands } = { commands: shapePaths, renderingMode: value };
|
|
43
|
-
const shapePoints: Point[][] = [this._extractPoints(fullPath.commands)];
|
|
44
|
-
const _redaction: PdfRedactionRegion[] = redaction._redactionRegion;
|
|
45
|
-
const {
|
|
46
|
-
updatedShapePoints,
|
|
47
|
-
intersectionsPoints,
|
|
48
|
-
isInSide,
|
|
49
|
-
isOutSide,
|
|
50
|
-
inSideRect,
|
|
51
|
-
totalRedactionPoints
|
|
52
|
-
} = this._clipAgainstRedactions(shapePoints, _redaction, page);
|
|
53
|
-
if (this._shouldSkipRendering(updatedShapePoints, fullPath.commands, isInSide)) {
|
|
54
|
-
this._clearPathAccumulator();
|
|
55
|
-
return -1;
|
|
56
|
-
}
|
|
57
|
-
const records: _PdfRecord[] = this._buildRenderingRecords(value,
|
|
58
|
-
updatedShapePoints,
|
|
59
|
-
intersectionsPoints,
|
|
60
|
-
isInSide,
|
|
61
|
-
isOutSide,
|
|
62
|
-
inSideRect,
|
|
63
|
-
totalRedactionPoints);
|
|
64
|
-
if (records && records.length > 0 && !isOutSide) {
|
|
65
|
-
for (let j: number = 0; j < records.length; j++) {
|
|
66
|
-
redaction._optimizeContent(records, j, '', stream);
|
|
67
|
-
}
|
|
68
|
-
}
|
|
69
|
-
this._clearPathAccumulator();
|
|
70
|
-
return k - 1;
|
|
71
|
-
}
|
|
72
|
-
switch (value) {
|
|
73
|
-
case _PdfPathCommands.moveTo:
|
|
74
|
-
startCount++;
|
|
75
|
-
if (startCount === 2) {
|
|
76
|
-
_currentPath = new _PdfPathFigure();
|
|
77
|
-
_currentPath._startPoint = { x: Number(element[0]), y: Number(element[1]) };
|
|
78
|
-
this._currentLocation = [Number(element[0]), Number(element[1])];
|
|
79
|
-
}
|
|
80
|
-
break;
|
|
81
|
-
case _PdfPathCommands.lineTo:
|
|
82
|
-
if (startCount === 2) {
|
|
83
|
-
_currentPath._segments.push(new _PdfLineSegment({ x: Number(element[0]), y: Number(element[1]) }));
|
|
84
|
-
}
|
|
85
|
-
break;
|
|
86
|
-
case _PdfPathCommands.curveTo:
|
|
87
|
-
if (startCount === 2) {
|
|
88
|
-
bezierSegment = new _PdfBezierSegment();
|
|
89
|
-
bezierSegment._point1 = { x: Number(element[0]), y: Number(element[1]) };
|
|
90
|
-
bezierSegment._point2 = { x: Number(element[2]), y: Number(element[3]) };
|
|
91
|
-
bezierSegment._point3 = { x: Number(element[4]), y: Number(element[5]) };
|
|
92
|
-
_currentPath._segments.push(bezierSegment);
|
|
93
|
-
}
|
|
94
|
-
break;
|
|
95
|
-
case _PdfPathCommands.curveToV:
|
|
96
|
-
if (startCount === 2) {
|
|
97
|
-
bezierSegment = new _PdfBezierSegment();
|
|
98
|
-
bezierSegment._point1 = { x: this._currentLocation[0], y: this._currentLocation[1] };
|
|
99
|
-
bezierSegment._point2 = { x: Number(element[0]), y: Number(element[1]) };
|
|
100
|
-
bezierSegment._point3 = { x: Number(element[2]), y: Number(element[3]) };
|
|
101
|
-
_currentPath._segments.push(bezierSegment);
|
|
102
|
-
}
|
|
103
|
-
break;
|
|
104
|
-
case _PdfPathCommands.curveToY:
|
|
105
|
-
if (startCount === 2) {
|
|
106
|
-
bezierSegment = new _PdfBezierSegment();
|
|
107
|
-
bezierSegment._point1 = { x: Number(element[0]), y: Number(element[1]) };
|
|
108
|
-
bezierSegment._point2 = { x: Number(element[2]), y: Number(element[3]) };
|
|
109
|
-
bezierSegment._point3 = bezierSegment._point2;
|
|
110
|
-
_currentPath._segments.push(bezierSegment);
|
|
111
|
-
}
|
|
112
|
-
break;
|
|
113
|
-
case _PdfPathCommands.closePath:
|
|
114
|
-
if (_currentPath) {
|
|
115
|
-
_currentPath._isClosed = true;
|
|
116
|
-
}
|
|
117
|
-
break;
|
|
118
|
-
default:
|
|
119
|
-
return -1;
|
|
120
|
-
}
|
|
121
|
-
}
|
|
122
|
-
return -1;
|
|
123
|
-
}
|
|
124
|
-
private _flattenIfNeeded(shapePaths: _PdfPathCommand[]): _PdfPathCommand[] {
|
|
125
|
-
for (let p: number = 0; p < shapePaths.length; p++) {
|
|
126
|
-
if (shapePaths[<number>p].operator.indexOf('c') !== -1) {
|
|
127
|
-
shapePaths = this._flattenPdfPathCommands(shapePaths);
|
|
128
|
-
break;
|
|
129
|
-
}
|
|
130
|
-
}
|
|
131
|
-
return shapePaths;
|
|
132
|
-
}
|
|
133
|
-
private _clipAgainstRedactions(shapePoints: Point[][], redactions: PdfRedactionRegion[], page: PdfPage): {
|
|
134
|
-
updatedShapePoints: Point[][],
|
|
135
|
-
intersectionsPoints: Point[],
|
|
136
|
-
isInSide: boolean,
|
|
137
|
-
isOutSide: boolean,
|
|
138
|
-
inSideRect: _PdfPathCommand[],
|
|
139
|
-
totalRedactionPoints: Point[][]
|
|
140
|
-
} {
|
|
141
|
-
const intersectionsPoints: Point[] = [];
|
|
142
|
-
const totalRedactionPoints: Point[][] = [];
|
|
143
|
-
let isInSide: boolean = false;
|
|
144
|
-
let isOutSide: boolean = false;
|
|
145
|
-
let inSideRect: _PdfPathCommand[];
|
|
146
|
-
for (const redaction of redactions) {
|
|
147
|
-
if (redaction._isTextOnly) {
|
|
148
|
-
continue;
|
|
149
|
-
}
|
|
150
|
-
const bounds: Rectangle = this._adjustRedactionBounds(redaction._bounds, shapePoints[0][0].y, page);
|
|
151
|
-
const redactionPath: _PdfPathCommand[] = this._rectToPathCommands(bounds);
|
|
152
|
-
const redactionPoints: Point[] = this._extractPoints(redactionPath);
|
|
153
|
-
totalRedactionPoints.push(redactionPoints);
|
|
154
|
-
const newNonRedactedPoints: Point[][] = [];
|
|
155
|
-
for (const shape of shapePoints) {
|
|
156
|
-
const source: _PdfPolygon = new _PdfPolygon(shape);
|
|
157
|
-
const clipPoly: _PdfPolygon = new _PdfPolygon(redactionPoints);
|
|
158
|
-
const clipped: Point[][] = source._clip(clipPoly, false, true);
|
|
159
|
-
intersectionsPoints.push(...source._globalIntersections);
|
|
160
|
-
newNonRedactedPoints.push(...clipped);
|
|
161
|
-
}
|
|
162
|
-
if (newNonRedactedPoints.length === 2) {
|
|
163
|
-
if (this._pointsArraysEqual(newNonRedactedPoints[1], redactionPoints)) {
|
|
164
|
-
isInSide = true;
|
|
165
|
-
newNonRedactedPoints.splice(1, 1);
|
|
166
|
-
inSideRect = redactionPath;
|
|
167
|
-
} else if (this._pointsArraysEqual(newNonRedactedPoints[0], redactionPoints)) {
|
|
168
|
-
isOutSide = true;
|
|
169
|
-
newNonRedactedPoints.splice(1, 1);
|
|
170
|
-
}
|
|
171
|
-
}
|
|
172
|
-
shapePoints = newNonRedactedPoints;
|
|
173
|
-
}
|
|
174
|
-
return { updatedShapePoints: shapePoints, intersectionsPoints, isInSide, isOutSide, inSideRect, totalRedactionPoints };
|
|
175
|
-
}
|
|
176
|
-
private _adjustRedactionBounds(bounds: Rectangle, y: number, page: PdfPage): Rectangle {
|
|
177
|
-
const adjusted: Rectangle = { ...bounds };
|
|
178
|
-
if (y < 0) {
|
|
179
|
-
adjusted.y = -adjusted.y;
|
|
180
|
-
adjusted.height = -adjusted.height;
|
|
181
|
-
} else {
|
|
182
|
-
adjusted.y = page.size[1] - adjusted.y - adjusted.height;
|
|
183
|
-
}
|
|
184
|
-
return adjusted;
|
|
185
|
-
}
|
|
186
|
-
private _shouldSkipRendering(shapePoints: Point[][], originalPoints: _PdfPathCommand[], isInSide: boolean): boolean {
|
|
187
|
-
return shapePoints.length === 0 ||
|
|
188
|
-
shapePoints.length === 1 &&
|
|
189
|
-
this._pointsArraysEqual(this._extractPoints(originalPoints), shapePoints[0]) &&
|
|
190
|
-
!isInSide;
|
|
191
|
-
}
|
|
192
|
-
private _buildRenderingRecords(
|
|
193
|
-
value: string,
|
|
194
|
-
shapePoints: Point[][],
|
|
195
|
-
intersectionsPoints: Point[],
|
|
196
|
-
isInSide: boolean,
|
|
197
|
-
isOutSide: boolean,
|
|
198
|
-
inSideRect: _PdfPathCommand[] | undefined,
|
|
199
|
-
totalRedactionPoints: Point[][]
|
|
200
|
-
): _PdfRecord[] {
|
|
201
|
-
const records: _PdfRecord[] = [];
|
|
202
|
-
if (value === _PdfPathCommands.drawStroke || value === _PdfPathCommands.drawCloseStroke) {
|
|
203
|
-
if (!isOutSide) {
|
|
204
|
-
shapePoints = this._removeRedactionPoints(this._removeDuplicatePoints(shapePoints), totalRedactionPoints);
|
|
205
|
-
records.push(...this._buildRecords(this._convertPointsToPath(shapePoints, intersectionsPoints)));
|
|
206
|
-
if (value === _PdfPathCommands.drawCloseStroke) {
|
|
207
|
-
records.push(new _PdfRecord('S', []));
|
|
208
|
-
}
|
|
209
|
-
}
|
|
210
|
-
} else if (value === _PdfPathCommands.fill || value === _PdfPathCommands.fillEvenOdd) {
|
|
211
|
-
records.push(...this._buildRecords(this._convertPointsToPath(shapePoints)));
|
|
212
|
-
if (isInSide && inSideRect) {
|
|
213
|
-
records.push(new _PdfRecord('h', []));
|
|
214
|
-
records.push(new _PdfRecord('f', []), new _PdfRecord('rg', ['1.000', '1.000', '1.000']));
|
|
215
|
-
records.push(...this._buildRecords(inSideRect));
|
|
216
|
-
}
|
|
217
|
-
} else {
|
|
218
|
-
records.push(...this._buildRecords(this._convertPointsToPath(shapePoints)));
|
|
219
|
-
if (!isOutSide) {
|
|
220
|
-
if (isInSide) {
|
|
221
|
-
records.push(new _PdfRecord('h', []));
|
|
222
|
-
}
|
|
223
|
-
records.push(new _PdfRecord('f', []));
|
|
224
|
-
shapePoints = this._removeRedactionPoints(this._removeDuplicatePoints(shapePoints), totalRedactionPoints);
|
|
225
|
-
records.push(...this._buildRecords(this._convertPointsToPath(shapePoints, intersectionsPoints)));
|
|
226
|
-
if (isInSide) {
|
|
227
|
-
records.push(new _PdfRecord('h', []));
|
|
228
|
-
}
|
|
229
|
-
records.push(new _PdfRecord('S', []));
|
|
230
|
-
}
|
|
231
|
-
if (isInSide && inSideRect) {
|
|
232
|
-
records.push(new _PdfRecord('rg', ['1.000', '1.000', '1.000']));
|
|
233
|
-
records.push(...this._buildRecords(inSideRect), new _PdfRecord('f', []));
|
|
234
|
-
}
|
|
235
|
-
}
|
|
236
|
-
return records;
|
|
237
|
-
}
|
|
238
|
-
private _getGeometry(figure: _PdfPathFigure): _PdfPathCommand[] {
|
|
239
|
-
this._pathAccumulator = [];
|
|
240
|
-
const point: Point = { x: figure._startPoint.x, y: figure._startPoint.y };
|
|
241
|
-
this._pathAccumulator.push({ operator: 'm', points: [ point ] });
|
|
242
|
-
for (const segment of figure._segments) {
|
|
243
|
-
if (segment instanceof _PdfLineSegment) {
|
|
244
|
-
const line: _PdfLineSegment = segment as _PdfLineSegment;
|
|
245
|
-
const points: Point = { x: line._point.x, y: line._point.y };
|
|
246
|
-
this._pathAccumulator.push({ operator: 'l', points: [ points ] });
|
|
247
|
-
} else if (segment instanceof _PdfBezierSegment) {
|
|
248
|
-
const bezier: _PdfBezierSegment = segment as _PdfBezierSegment;
|
|
249
|
-
const points: Point[] = [
|
|
250
|
-
{ x: bezier._point1.x, y: bezier._point1.y },
|
|
251
|
-
{ x: bezier._point2.x, y: bezier._point2.y },
|
|
252
|
-
{ x: bezier._point3.x, y: bezier._point3.y }
|
|
253
|
-
];
|
|
254
|
-
this._pathAccumulator.push({ operator: 'c', points: points });
|
|
255
|
-
}
|
|
256
|
-
}
|
|
257
|
-
if (figure._isClosed) {
|
|
258
|
-
this._pathAccumulator.push({ operator: 'h', points: [] });
|
|
259
|
-
}
|
|
260
|
-
return this._pathAccumulator;
|
|
261
|
-
}
|
|
262
|
-
private _isValidRectangle(recordCollection: _PdfRecord[], i: number): boolean {
|
|
263
|
-
for (const offset of [1, 2, 3]) {
|
|
264
|
-
const item: _PdfRecord = recordCollection[i + offset];
|
|
265
|
-
if (item && item._operator === 'n') {
|
|
266
|
-
return false;
|
|
267
|
-
}
|
|
268
|
-
}
|
|
269
|
-
return true;
|
|
270
|
-
}
|
|
271
|
-
_processRectangle(recordCollection: _PdfRecord[], i: number, element: string[]): _PdfRecord[] {
|
|
272
|
-
if (this._isValidRectangle(recordCollection, i)) {
|
|
273
|
-
return this._generateRectanglePath(recordCollection, i, element);
|
|
274
|
-
}
|
|
275
|
-
return [];
|
|
276
|
-
}
|
|
277
|
-
private _generateRectanglePath(recordCollection: _PdfRecord[], i: number, element: string[]): _PdfRecord[] {
|
|
278
|
-
const records: _PdfRecord[] = [];
|
|
279
|
-
const rect: Rectangle = {
|
|
280
|
-
x: parseFloat(element[0]),
|
|
281
|
-
y: parseFloat(element[1]),
|
|
282
|
-
width: parseFloat(element[2]),
|
|
283
|
-
height: parseFloat(element[3])
|
|
284
|
-
};
|
|
285
|
-
const pathCommands: _PdfPathCommand[] = this._rectToPathCommands(rect);
|
|
286
|
-
for (const cmd of pathCommands) {
|
|
287
|
-
if (cmd.operator === 'h' && recordCollection[i + 1]._operator !== 'h') {
|
|
288
|
-
records.push(new _PdfRecord('h', []));
|
|
289
|
-
} else {
|
|
290
|
-
for (const pt of cmd.points) {
|
|
291
|
-
const operands: string[] = [pt.x.toFixed(3), pt.y.toFixed(3)];
|
|
292
|
-
records.push(new _PdfRecord(cmd.operator, operands));
|
|
293
|
-
}
|
|
294
|
-
}
|
|
295
|
-
}
|
|
296
|
-
return records;
|
|
297
|
-
}
|
|
298
|
-
private _rectToPathCommands(rect: Rectangle): _PdfPathCommand[] {
|
|
299
|
-
return [
|
|
300
|
-
{
|
|
301
|
-
operator: 'm',
|
|
302
|
-
points: [{ x: rect.x + rect.width, y: rect.y + rect.height }]
|
|
303
|
-
},
|
|
304
|
-
{
|
|
305
|
-
operator: 'l',
|
|
306
|
-
points: [{ x: rect.x, y: rect.y + rect.height }]
|
|
307
|
-
},
|
|
308
|
-
{
|
|
309
|
-
operator: 'l',
|
|
310
|
-
points: [{ x: rect.x, y: rect.y }]
|
|
311
|
-
},
|
|
312
|
-
{
|
|
313
|
-
operator: 'l',
|
|
314
|
-
points: [{ x: rect.x + rect.width, y: rect.y }]
|
|
315
|
-
},
|
|
316
|
-
{
|
|
317
|
-
operator: 'h',
|
|
318
|
-
points: []
|
|
319
|
-
}
|
|
320
|
-
];
|
|
321
|
-
}
|
|
322
|
-
private _extractPoints(commands: _PdfPathCommand[]): Point[] {
|
|
323
|
-
const points: Point[] = [];
|
|
324
|
-
for (const cmd of commands) {
|
|
325
|
-
points.push(...cmd.points);
|
|
326
|
-
}
|
|
327
|
-
return points;
|
|
328
|
-
}
|
|
329
|
-
private _isIntersecting(pt: Point, polygonIntersections?: Point[]): boolean {
|
|
330
|
-
if (!polygonIntersections) {
|
|
331
|
-
return false;
|
|
332
|
-
}
|
|
333
|
-
for (let i: number = 0; i < polygonIntersections.length; i++) {
|
|
334
|
-
if (polygonIntersections[<number>i].x === pt.x && polygonIntersections[<number>i].y === pt.y) {
|
|
335
|
-
return true;
|
|
336
|
-
}
|
|
337
|
-
}
|
|
338
|
-
return false;
|
|
339
|
-
}
|
|
340
|
-
private _convertPointsToPath(input: Point[][], polygonIntersections?: Point[]): _PdfPathCommand[] {
|
|
341
|
-
const commands: _PdfPathCommand[] = [];
|
|
342
|
-
const hasIntersections: boolean = polygonIntersections && polygonIntersections.length > 0;
|
|
343
|
-
for (const points of input) {
|
|
344
|
-
if (points.length === 0) {
|
|
345
|
-
continue;
|
|
346
|
-
}
|
|
347
|
-
commands.push({ operator: 'm', points: [points[0]] });
|
|
348
|
-
for (let i: number = 1; i < points.length; i++) {
|
|
349
|
-
const prevPoint: Point = points[i - 1];
|
|
350
|
-
const currentPoint: Point = points[<number>i];
|
|
351
|
-
if (hasIntersections) {
|
|
352
|
-
const prevIsIntersect: boolean = this._isIntersecting(prevPoint, polygonIntersections);
|
|
353
|
-
const currIsIntersect: boolean = this._isIntersecting(currentPoint, polygonIntersections);
|
|
354
|
-
if (prevIsIntersect && currIsIntersect) {
|
|
355
|
-
commands.push({ operator: 'm', points: [currentPoint] });
|
|
356
|
-
} else {
|
|
357
|
-
commands.push({ operator: 'l', points: [currentPoint] });
|
|
358
|
-
}
|
|
359
|
-
} else {
|
|
360
|
-
commands.push({ operator: 'l', points: [currentPoint] });
|
|
361
|
-
}
|
|
362
|
-
}
|
|
363
|
-
}
|
|
364
|
-
return commands;
|
|
365
|
-
}
|
|
366
|
-
private _flattenBezierCurve(p0: Point, p1: Point, p2: Point, p3: Point, segments: number = 8): Point[] {
|
|
367
|
-
const points: Point[] = [];
|
|
368
|
-
for (let i: number = 1; i <= segments; i++) {
|
|
369
|
-
const t: number = i / segments;
|
|
370
|
-
const mt: number = 1 - t;
|
|
371
|
-
const x: number = mt * mt * mt * p0.x +
|
|
372
|
-
3 * mt * mt * t * p1.x +
|
|
373
|
-
3 * mt * t * t * p2.x +
|
|
374
|
-
t * t * t * p3.x;
|
|
375
|
-
const y: number = mt * mt * mt * p0.y +
|
|
376
|
-
3 * mt * mt * t * p1.y +
|
|
377
|
-
3 * mt * t * t * p2.y +
|
|
378
|
-
t * t * t * p3.y;
|
|
379
|
-
points.push({ x, y });
|
|
380
|
-
}
|
|
381
|
-
return points;
|
|
382
|
-
}
|
|
383
|
-
private _flattenPdfPathCommands(commands: _PdfPathCommand[], segmentsPerCurve: number = 8): _PdfPathCommand[] {
|
|
384
|
-
const flattened: _PdfPathCommand[] = [];
|
|
385
|
-
let currentPoint: Point;
|
|
386
|
-
for (const cmd of commands) {
|
|
387
|
-
if (cmd.operator === 'm') {
|
|
388
|
-
flattened.push(cmd);
|
|
389
|
-
currentPoint = cmd.points[0];
|
|
390
|
-
} else if (cmd.operator === 'l') {
|
|
391
|
-
flattened.push(cmd);
|
|
392
|
-
currentPoint = cmd.points[0];
|
|
393
|
-
} else if (cmd.operator === 'c') {
|
|
394
|
-
if (!currentPoint) {
|
|
395
|
-
throw new Error('Invalid path: curve without current point');
|
|
396
|
-
}
|
|
397
|
-
const [cp1, cp2, endPoint] = cmd.points;
|
|
398
|
-
const flattenedPoints: Point[] = this._flattenBezierCurve(currentPoint, cp1, cp2, endPoint, segmentsPerCurve);
|
|
399
|
-
for (const pt of flattenedPoints) {
|
|
400
|
-
flattened.push({
|
|
401
|
-
operator: 'l',
|
|
402
|
-
points: [pt]
|
|
403
|
-
});
|
|
404
|
-
}
|
|
405
|
-
currentPoint = endPoint;
|
|
406
|
-
} else if (cmd.operator === 'h') {
|
|
407
|
-
flattened.push(cmd);
|
|
408
|
-
}
|
|
409
|
-
}
|
|
410
|
-
return flattened;
|
|
411
|
-
}
|
|
412
|
-
private _pointsArraysEqual(a: Point[], b: Point[]): boolean {
|
|
413
|
-
if (a.length !== b.length) {
|
|
414
|
-
return false;
|
|
415
|
-
}
|
|
416
|
-
return a.every((point: Point, i: any) => point.x === b[<number>i].x && //eslint-disable-line
|
|
417
|
-
point.y === b[<number>i].y);
|
|
418
|
-
}
|
|
419
|
-
private _removeDuplicatePoints(pointsArrays: Point[][]): Point[][] {
|
|
420
|
-
return pointsArrays.map((points: Point[]) => {
|
|
421
|
-
const uniquePoints: Set<string> = new Set<string>();
|
|
422
|
-
return points.filter((pt: Point) => {
|
|
423
|
-
const key: string = `${pt.x},${pt.y}`;
|
|
424
|
-
if (uniquePoints.has(key)) {
|
|
425
|
-
return false;
|
|
426
|
-
} else {
|
|
427
|
-
uniquePoints.add(key);
|
|
428
|
-
return true;
|
|
429
|
-
}
|
|
430
|
-
});
|
|
431
|
-
});
|
|
432
|
-
}
|
|
433
|
-
private _removeRedactionPoints(
|
|
434
|
-
nonRedactedPointsArray: Point[][],
|
|
435
|
-
redactionPointsArray: Point[][]
|
|
436
|
-
): Point[][] {
|
|
437
|
-
const redactionPoints: Set<string> = new Set<string>();
|
|
438
|
-
for (const redactionArray of redactionPointsArray) {
|
|
439
|
-
for (const pt of redactionArray) {
|
|
440
|
-
redactionPoints.add(`${pt.x},${pt.y}`);
|
|
441
|
-
}
|
|
442
|
-
}
|
|
443
|
-
const filteredPointsArray: Point[][] = nonRedactedPointsArray.map((points: Point[]) =>
|
|
444
|
-
points.filter((pt: Point) => !redactionPoints.has(`${pt.x},${pt.y}`))
|
|
445
|
-
);
|
|
446
|
-
return filteredPointsArray;
|
|
447
|
-
}
|
|
448
|
-
private _buildRecords(commands: _PdfPathCommand[]): _PdfRecord[] {
|
|
449
|
-
const result: _PdfRecord[] = [];
|
|
450
|
-
for (let a: number = 0; a < commands.length; a++) {
|
|
451
|
-
const cmd: _PdfPathCommand = commands[<number>a];
|
|
452
|
-
for (let b: number = 0; b < cmd.points.length; b++) {
|
|
453
|
-
const pt: Point = cmd.points[<number>b];
|
|
454
|
-
result.push(new _PdfRecord(cmd.operator, [pt.x.toFixed(3), pt.y.toFixed(3)]));
|
|
455
|
-
}
|
|
456
|
-
}
|
|
457
|
-
return result;
|
|
458
|
-
}
|
|
459
|
-
}
|
|
460
|
-
export type _PdfPathCommand = {
|
|
461
|
-
operator: string;
|
|
462
|
-
points: Point[];
|
|
463
|
-
};
|
|
464
|
-
enum _PdfPathCommands {
|
|
465
|
-
drawStroke = 'S',
|
|
466
|
-
drawCloseStroke = 's',
|
|
467
|
-
fill = 'f',
|
|
468
|
-
fillEvenOdd = 'f*',
|
|
469
|
-
fillStroke = 'B',
|
|
470
|
-
fillEvenOddStroke = 'B*',
|
|
471
|
-
fillCloseStroke = 'b',
|
|
472
|
-
fillEvenOddCloseStroke = 'b*',
|
|
473
|
-
moveTo = 'm',
|
|
474
|
-
lineTo = 'l',
|
|
475
|
-
curveTo = 'c',
|
|
476
|
-
curveToV = 'v',
|
|
477
|
-
curveToY = 'y',
|
|
478
|
-
closePath = 'h',
|
|
479
|
-
}
|
|
@@ -1,12 +0,0 @@
|
|
|
1
|
-
import { TextGlyph } from '../text-structure';
|
|
2
|
-
export declare class _TextGlyphMapper {
|
|
3
|
-
_text: string;
|
|
4
|
-
_glyph: TextGlyph[];
|
|
5
|
-
_isHex: boolean;
|
|
6
|
-
text: string;
|
|
7
|
-
glyph: TextGlyph[];
|
|
8
|
-
_applyEscapeSequence(text: string): string;
|
|
9
|
-
_getText(): string;
|
|
10
|
-
_replacedText(text: string, glyphs: TextGlyph[]): string;
|
|
11
|
-
_getReplacedCharacter(glyphs: TextGlyph[]): number;
|
|
12
|
-
}
|
|
@@ -1,153 +0,0 @@
|
|
|
1
|
-
import { TextGlyph } from '../text-structure';
|
|
2
|
-
|
|
3
|
-
export class _TextGlyphMapper {
|
|
4
|
-
_text: string;
|
|
5
|
-
_glyph: TextGlyph[];
|
|
6
|
-
_isHex: boolean = false;
|
|
7
|
-
set text(value: string) {
|
|
8
|
-
this._text = value;
|
|
9
|
-
}
|
|
10
|
-
get text(): string {
|
|
11
|
-
return this._text;
|
|
12
|
-
}
|
|
13
|
-
set glyph(value: TextGlyph[]) {
|
|
14
|
-
this._glyph = value;
|
|
15
|
-
}
|
|
16
|
-
get glyph(): TextGlyph[] {
|
|
17
|
-
return this._glyph;
|
|
18
|
-
}
|
|
19
|
-
_applyEscapeSequence(text: string): string {
|
|
20
|
-
let escapedText: string = text;
|
|
21
|
-
if (text.indexOf('(') !== -1) {
|
|
22
|
-
escapedText = escapedText.replace(/\(/g, '\\(');
|
|
23
|
-
}
|
|
24
|
-
if (text.indexOf(')') !== -1) {
|
|
25
|
-
escapedText = escapedText.replace(/\)/g, '\\)');
|
|
26
|
-
}
|
|
27
|
-
if (text.indexOf("'") !== -1) { // eslint-disable-line
|
|
28
|
-
escapedText = escapedText.replace(/'/g, "\\'"); // eslint-disable-line
|
|
29
|
-
}
|
|
30
|
-
if (text.indexOf('\\') !== -1) {
|
|
31
|
-
escapedText = escapedText.replace(/\\/g, '\\\\');
|
|
32
|
-
}
|
|
33
|
-
if (text.indexOf('\b') !== -1) {
|
|
34
|
-
escapedText = escapedText.replace(/\b/g, '\\b');
|
|
35
|
-
}
|
|
36
|
-
if (text.indexOf('\f') !== -1) {
|
|
37
|
-
escapedText = escapedText.replace(/\f/g, '\\f');
|
|
38
|
-
}
|
|
39
|
-
if (text.indexOf('\n') !== -1) {
|
|
40
|
-
escapedText = escapedText.replace(/\n/g, '\\n');
|
|
41
|
-
}
|
|
42
|
-
if (text.indexOf('\r') !== -1) {
|
|
43
|
-
escapedText = escapedText.replace(/\r/g, '\\r');
|
|
44
|
-
}
|
|
45
|
-
return escapedText;
|
|
46
|
-
}
|
|
47
|
-
_getText(): string {
|
|
48
|
-
if (typeof (this.glyph) === 'undefined') {
|
|
49
|
-
return this.text;
|
|
50
|
-
} else {
|
|
51
|
-
let finalText: string = '';
|
|
52
|
-
let currentText: string = '';
|
|
53
|
-
const subString: boolean = this.text.length >= 2;
|
|
54
|
-
const start: boolean = this.text.startsWith('(');
|
|
55
|
-
const end: boolean = this.text.endsWith(')');
|
|
56
|
-
if (subString && start && !end) {
|
|
57
|
-
currentText = this.text.substring(1, this.text.length);
|
|
58
|
-
} else if (subString && !start && end) {
|
|
59
|
-
currentText = this.text.substring(0, this.text.length - 1);
|
|
60
|
-
} else if (subString) {
|
|
61
|
-
currentText = this.text.substring(1, this.text.length - 1);
|
|
62
|
-
}
|
|
63
|
-
let replaceText: string = '';
|
|
64
|
-
let otherText: string = '';
|
|
65
|
-
let glyphs: TextGlyph[] = [];
|
|
66
|
-
const glyphDictionary: Map<string, TextGlyph[]> = new Map<string, TextGlyph[]>();
|
|
67
|
-
const dictionary: Map<string, string> = new Map<string, string> ();
|
|
68
|
-
let rTcount: number = 0;
|
|
69
|
-
let roTcount: number = 0;
|
|
70
|
-
let isHex: boolean = false;
|
|
71
|
-
for (let i: number = 0; i < this.glyph.length; i++) {
|
|
72
|
-
if (this.glyph[Number.parseInt(i.toString(), 10)]._isReplace) {
|
|
73
|
-
if (otherText !== '') {
|
|
74
|
-
dictionary.set('O-' + roTcount++, otherText);
|
|
75
|
-
otherText = '';
|
|
76
|
-
isHex = this.glyph[Number.parseInt(i.toString(), 10)]._isHex;
|
|
77
|
-
}
|
|
78
|
-
glyphs.push(this.glyph[Number.parseInt(i.toString(), 10)]);
|
|
79
|
-
replaceText += this.glyph[Number.parseInt(i.toString(), 10)].text;
|
|
80
|
-
} else {
|
|
81
|
-
if (replaceText !== '') {
|
|
82
|
-
const key: string = 'R-' + rTcount++;
|
|
83
|
-
glyphDictionary.set(key, glyphs);
|
|
84
|
-
dictionary.set(key, replaceText);
|
|
85
|
-
glyphs = [];
|
|
86
|
-
replaceText = '';
|
|
87
|
-
}
|
|
88
|
-
isHex = this.glyph[Number.parseInt(i.toString(), 10)]._isHex;
|
|
89
|
-
const text: string = this.glyph[Number.parseInt(i.toString(), 10)].text;
|
|
90
|
-
if (!isHex) {
|
|
91
|
-
otherText += this._applyEscapeSequence(text);
|
|
92
|
-
} else {
|
|
93
|
-
otherText += text;
|
|
94
|
-
}
|
|
95
|
-
}
|
|
96
|
-
}
|
|
97
|
-
if (replaceText !== '') {
|
|
98
|
-
const key: string = 'R-' + rTcount++;
|
|
99
|
-
glyphDictionary.set(key, glyphs);
|
|
100
|
-
dictionary.set(key, replaceText);
|
|
101
|
-
glyphs = [];
|
|
102
|
-
replaceText = '';
|
|
103
|
-
}
|
|
104
|
-
if (otherText !== '') {
|
|
105
|
-
const key: string = 'O-' + roTcount++;
|
|
106
|
-
dictionary.set(key, otherText);
|
|
107
|
-
otherText = '';
|
|
108
|
-
}
|
|
109
|
-
dictionary.forEach((value: string, key: string) => {
|
|
110
|
-
if (key.indexOf('O-') !== -1) {
|
|
111
|
-
if (isHex) {
|
|
112
|
-
finalText += '<' + value + '>';
|
|
113
|
-
} else {
|
|
114
|
-
finalText += '(' + value + ')';
|
|
115
|
-
}
|
|
116
|
-
} else {
|
|
117
|
-
finalText += ' -' + this._getReplacedCharacter(glyphDictionary.get(key)) + ' ';
|
|
118
|
-
currentText = this._replacedText(currentText, glyphDictionary.get(key));
|
|
119
|
-
}
|
|
120
|
-
});
|
|
121
|
-
return finalText;
|
|
122
|
-
}
|
|
123
|
-
}
|
|
124
|
-
_replacedText(text: string, glyphs: TextGlyph[]): string {
|
|
125
|
-
if (!text) {
|
|
126
|
-
return text;
|
|
127
|
-
}
|
|
128
|
-
let currentText: string = text;
|
|
129
|
-
let count: number = 0;
|
|
130
|
-
for (const gly of glyphs) {
|
|
131
|
-
const unicode: string = gly.text;
|
|
132
|
-
if (unicode) {
|
|
133
|
-
count += unicode.length;
|
|
134
|
-
}
|
|
135
|
-
}
|
|
136
|
-
currentText = currentText.substring(count);
|
|
137
|
-
return currentText;
|
|
138
|
-
}
|
|
139
|
-
_getReplacedCharacter(glyphs: TextGlyph[]): number {
|
|
140
|
-
let totalWidth: number = 0;
|
|
141
|
-
for (let i: number = 0; i < glyphs.length; i++) {
|
|
142
|
-
const width: number = glyphs[Number.parseInt(i.toString(), 10)]._width;
|
|
143
|
-
if (glyphs[Number.parseInt(i.toString(), 10)].text !== ' ' ) {
|
|
144
|
-
totalWidth += width;
|
|
145
|
-
} else {
|
|
146
|
-
const actualFontSize: number = (0.001 * width * glyphs[Number.parseInt(i.toString(), 10)].fontSize);
|
|
147
|
-
totalWidth += (width + ((width / actualFontSize) * glyphs[Number.parseInt(i.toString(), 10)]._charSpacing) +
|
|
148
|
-
((width / actualFontSize) * glyphs[Number.parseInt(i.toString(), 10)]._wordSpacing));
|
|
149
|
-
}
|
|
150
|
-
}
|
|
151
|
-
return totalWidth;
|
|
152
|
-
}
|
|
153
|
-
}
|
|
@@ -1,24 +0,0 @@
|
|
|
1
|
-
export declare class _PdfBinaryCharacterMapReader {
|
|
2
|
-
_maximumSize: number;
|
|
3
|
-
_convertHexToInt(data: Uint8Array, size: number): number;
|
|
4
|
-
_hexArrayToString(data: any, size: number): string;
|
|
5
|
-
_addHexData(data: Uint8Array, incrementData: Uint8Array, size: number): void;
|
|
6
|
-
_performHexIncrement(data: Uint8Array, size: number): void;
|
|
7
|
-
_process(data: any, characterMap: any, enhance: any): any;
|
|
8
|
-
}
|
|
9
|
-
export declare class _PdfBinaryCMapStream {
|
|
10
|
-
_buffer: any;
|
|
11
|
-
_pos: number;
|
|
12
|
-
_end: number;
|
|
13
|
-
_tempBuffer: Uint8Array;
|
|
14
|
-
_maximumSize: number;
|
|
15
|
-
_maxEncodedNumberSize: number;
|
|
16
|
-
constructor(data: any);
|
|
17
|
-
_readByteData(): any;
|
|
18
|
-
_readNumber(): number;
|
|
19
|
-
_readSignedData(): number;
|
|
20
|
-
_readHexData(number: any, size: number): void;
|
|
21
|
-
_readHexDataNumber(number: any, size: number): void;
|
|
22
|
-
_readHexSignedData(number: any, size: number): void;
|
|
23
|
-
_readStringFromData(): string;
|
|
24
|
-
}
|