@mlightcad/cad-pdf-plugin 1.8.0-preview.2 → 1.8.0-preview.4
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/LICENSE +21 -21
- package/README.md +280 -186
- package/dist/cad-pdf-plugin-register.js +29 -11
- package/dist/cad-pdf-plugin-register.umd.cjs +1 -1
- package/dist/cad-pdf-plugin.js +17568 -8428
- package/dist/cad-pdf-plugin.umd.cjs +847 -13
- package/lib/AcApConvertToPdfCmd.d.ts.map +1 -1
- package/lib/AcApConvertToPdfCmd.js +14 -3
- package/lib/AcApConvertToPdfCmd.js.map +1 -1
- package/lib/AcApImportPdfCmd.d.ts +5 -3
- package/lib/AcApImportPdfCmd.d.ts.map +1 -1
- package/lib/AcApImportPdfCmd.js +5 -3
- package/lib/AcApImportPdfCmd.js.map +1 -1
- package/lib/AcApImportPdfPromptCmd.d.ts +16 -0
- package/lib/AcApImportPdfPromptCmd.d.ts.map +1 -0
- package/lib/AcApImportPdfPromptCmd.js +89 -0
- package/lib/AcApImportPdfPromptCmd.js.map +1 -0
- package/lib/AcApPdfBlockCmd.d.ts +15 -0
- package/lib/AcApPdfBlockCmd.d.ts.map +1 -0
- package/lib/AcApPdfBlockCmd.js +75 -0
- package/lib/AcApPdfBlockCmd.js.map +1 -0
- package/lib/AcApPdfDimCmd.d.ts +20 -0
- package/lib/AcApPdfDimCmd.d.ts.map +1 -0
- package/lib/AcApPdfDimCmd.js +413 -0
- package/lib/AcApPdfDimCmd.js.map +1 -0
- package/lib/AcApPdfDimSession.d.ts +82 -0
- package/lib/AcApPdfDimSession.d.ts.map +1 -0
- package/lib/AcApPdfDimSession.js +252 -0
- package/lib/AcApPdfDimSession.js.map +1 -0
- package/lib/AcApPdfFontResolver.d.ts.map +1 -1
- package/lib/AcApPdfFontResolver.js +2 -5
- package/lib/AcApPdfFontResolver.js.map +1 -1
- package/lib/AcApPdfHatchCmd.d.ts +33 -0
- package/lib/AcApPdfHatchCmd.d.ts.map +1 -0
- package/lib/AcApPdfHatchCmd.js +411 -0
- package/lib/AcApPdfHatchCmd.js.map +1 -0
- package/lib/AcApPdfHatchSession.d.ts +122 -0
- package/lib/AcApPdfHatchSession.d.ts.map +1 -0
- package/lib/AcApPdfHatchSession.js +357 -0
- package/lib/AcApPdfHatchSession.js.map +1 -0
- package/lib/AcApPdfImportConvertor.d.ts +47 -5
- package/lib/AcApPdfImportConvertor.d.ts.map +1 -1
- package/lib/AcApPdfImportConvertor.js +999 -108
- package/lib/AcApPdfImportConvertor.js.map +1 -1
- package/lib/AcApPdfImportOptions.d.ts +116 -0
- package/lib/AcApPdfImportOptions.d.ts.map +1 -0
- package/lib/AcApPdfImportOptions.js +31 -0
- package/lib/AcApPdfImportOptions.js.map +1 -0
- package/lib/AcApPdfImportResources.d.ts +41 -0
- package/lib/AcApPdfImportResources.d.ts.map +1 -0
- package/lib/AcApPdfImportResources.js +52 -0
- package/lib/AcApPdfImportResources.js.map +1 -0
- package/lib/AcApPdfPlugin.d.ts +3 -3
- package/lib/AcApPdfPlugin.d.ts.map +1 -1
- package/lib/AcApPdfPlugin.js +23 -5
- package/lib/AcApPdfPlugin.js.map +1 -1
- package/lib/AcApPdfScaleCmd.d.ts +22 -0
- package/lib/AcApPdfScaleCmd.d.ts.map +1 -0
- package/lib/AcApPdfScaleCmd.js +185 -0
- package/lib/AcApPdfScaleCmd.js.map +1 -0
- package/lib/AcApPdfTextCmd.d.ts +73 -0
- package/lib/AcApPdfTextCmd.d.ts.map +1 -0
- package/lib/AcApPdfTextCmd.js +777 -0
- package/lib/AcApPdfTextCmd.js.map +1 -0
- package/lib/AcApPdfTextSession.d.ts +232 -0
- package/lib/AcApPdfTextSession.d.ts.map +1 -0
- package/lib/AcApPdfTextSession.js +826 -0
- package/lib/AcApPdfTextSession.js.map +1 -0
- package/lib/acapPdfI18n.d.ts +11 -0
- package/lib/acapPdfI18n.d.ts.map +1 -0
- package/lib/acapPdfI18n.js +57 -0
- package/lib/acapPdfI18n.js.map +1 -0
- package/lib/acapPdfPrompts.d.ts +12 -0
- package/lib/acapPdfPrompts.d.ts.map +1 -0
- package/lib/acapPdfPrompts.js +100 -0
- package/lib/acapPdfPrompts.js.map +1 -0
- package/lib/index.d.ts +28 -0
- package/lib/index.d.ts.map +1 -1
- package/lib/index.js +28 -0
- package/lib/index.js.map +1 -1
- package/lib/pdfDeprecatedMatching.d.ts +27 -0
- package/lib/pdfDeprecatedMatching.d.ts.map +1 -0
- package/lib/pdfDeprecatedMatching.js +20 -0
- package/lib/pdfDeprecatedMatching.js.map +1 -0
- package/lib/pdfDimStrokeTexts.d.ts +55 -0
- package/lib/pdfDimStrokeTexts.d.ts.map +1 -0
- package/lib/pdfDimStrokeTexts.js +274 -0
- package/lib/pdfDimStrokeTexts.js.map +1 -0
- package/lib/pdfDimensionConvert.d.ts +80 -0
- package/lib/pdfDimensionConvert.d.ts.map +1 -0
- package/lib/pdfDimensionConvert.js +566 -0
- package/lib/pdfDimensionConvert.js.map +1 -0
- package/lib/pdfEntityStrokes.d.ts +13 -0
- package/lib/pdfEntityStrokes.d.ts.map +1 -0
- package/lib/pdfEntityStrokes.js +86 -0
- package/lib/pdfEntityStrokes.js.map +1 -0
- package/lib/pdfHatchRecover.d.ts +57 -0
- package/lib/pdfHatchRecover.d.ts.map +1 -0
- package/lib/pdfHatchRecover.js +315 -0
- package/lib/pdfHatchRecover.js.map +1 -0
- package/lib/pdfImportAppend.d.ts +24 -0
- package/lib/pdfImportAppend.d.ts.map +1 -0
- package/lib/pdfImportAppend.js +35 -0
- package/lib/pdfImportAppend.js.map +1 -0
- package/lib/pdfImportEntities.d.ts +63 -0
- package/lib/pdfImportEntities.d.ts.map +1 -0
- package/lib/pdfImportEntities.js +307 -0
- package/lib/pdfImportEntities.js.map +1 -0
- package/lib/pdfImportImages.d.ts +90 -0
- package/lib/pdfImportImages.d.ts.map +1 -0
- package/lib/pdfImportImages.js +294 -0
- package/lib/pdfImportImages.js.map +1 -0
- package/lib/pdfImportShapes.d.ts +63 -0
- package/lib/pdfImportShapes.d.ts.map +1 -0
- package/lib/pdfImportShapes.js +248 -0
- package/lib/pdfImportShapes.js.map +1 -0
- package/lib/pdfVectorImport.d.ts +218 -5
- package/lib/pdfVectorImport.d.ts.map +1 -1
- package/lib/pdfVectorImport.js +566 -98
- package/lib/pdfVectorImport.js.map +1 -1
- package/lib/recognition/pdfCurveRecognition.d.ts +91 -0
- package/lib/recognition/pdfCurveRecognition.d.ts.map +1 -0
- package/lib/recognition/pdfCurveRecognition.js +506 -0
- package/lib/recognition/pdfCurveRecognition.js.map +1 -0
- package/lib/recognition/pdfDimDigitRecognition.d.ts +18 -0
- package/lib/recognition/pdfDimDigitRecognition.d.ts.map +1 -0
- package/lib/recognition/pdfDimDigitRecognition.js +520 -0
- package/lib/recognition/pdfDimDigitRecognition.js.map +1 -0
- package/lib/recognition/pdfDimensionPattern.d.ts +173 -0
- package/lib/recognition/pdfDimensionPattern.d.ts.map +1 -0
- package/lib/recognition/pdfDimensionPattern.js +1023 -0
- package/lib/recognition/pdfDimensionPattern.js.map +1 -0
- package/lib/recognition/pdfFormBlocks.d.ts +58 -0
- package/lib/recognition/pdfFormBlocks.d.ts.map +1 -0
- package/lib/recognition/pdfFormBlocks.js +260 -0
- package/lib/recognition/pdfFormBlocks.js.map +1 -0
- package/lib/recognition/pdfGlyphClustering.d.ts +81 -0
- package/lib/recognition/pdfGlyphClustering.d.ts.map +1 -0
- package/lib/recognition/pdfGlyphClustering.js +1005 -0
- package/lib/recognition/pdfGlyphClustering.js.map +1 -0
- package/lib/recognition/pdfGlyphDictionary.d.ts +49 -0
- package/lib/recognition/pdfGlyphDictionary.d.ts.map +1 -0
- package/lib/recognition/pdfGlyphDictionary.js +188 -0
- package/lib/recognition/pdfGlyphDictionary.js.map +1 -0
- package/lib/recognition/pdfHatchFaces.d.ts +84 -0
- package/lib/recognition/pdfHatchFaces.d.ts.map +1 -0
- package/lib/recognition/pdfHatchFaces.js +1285 -0
- package/lib/recognition/pdfHatchFaces.js.map +1 -0
- package/lib/recognition/pdfHatchRecognition.d.ts +222 -0
- package/lib/recognition/pdfHatchRecognition.d.ts.map +1 -0
- package/lib/recognition/pdfHatchRecognition.js +3781 -0
- package/lib/recognition/pdfHatchRecognition.js.map +1 -0
- package/lib/recognition/pdfRecGeometry.d.ts +67 -0
- package/lib/recognition/pdfRecGeometry.d.ts.map +1 -0
- package/lib/recognition/pdfRecGeometry.js +365 -0
- package/lib/recognition/pdfRecGeometry.js.map +1 -0
- package/lib/recognition/pdfTextFontKind.d.ts +16 -0
- package/lib/recognition/pdfTextFontKind.d.ts.map +1 -0
- package/lib/recognition/pdfTextFontKind.js +51 -0
- package/lib/recognition/pdfTextFontKind.js.map +1 -0
- package/lib/recognition/pdfTextMerge.d.ts +71 -0
- package/lib/recognition/pdfTextMerge.d.ts.map +1 -0
- package/lib/recognition/pdfTextMerge.js +382 -0
- package/lib/recognition/pdfTextMerge.js.map +1 -0
- package/lib/recognition/pdfTextRunMerge.d.ts +28 -0
- package/lib/recognition/pdfTextRunMerge.d.ts.map +1 -0
- package/lib/recognition/pdfTextRunMerge.js +90 -0
- package/lib/recognition/pdfTextRunMerge.js.map +1 -0
- package/lib/register.d.ts +8 -2
- package/lib/register.d.ts.map +1 -1
- package/lib/register.js +29 -4
- package/lib/register.js.map +1 -1
- package/lib/ui/AcUiPdfDimPanel.d.ts +55 -0
- package/lib/ui/AcUiPdfDimPanel.d.ts.map +1 -0
- package/lib/ui/AcUiPdfDimPanel.js +347 -0
- package/lib/ui/AcUiPdfDimPanel.js.map +1 -0
- package/lib/ui/AcUiPdfHatchPanel.d.ts +57 -0
- package/lib/ui/AcUiPdfHatchPanel.d.ts.map +1 -0
- package/lib/ui/AcUiPdfHatchPanel.js +420 -0
- package/lib/ui/AcUiPdfHatchPanel.js.map +1 -0
- package/lib/ui/AcUiPdfImportDialog.d.ts +120 -0
- package/lib/ui/AcUiPdfImportDialog.d.ts.map +1 -0
- package/lib/ui/AcUiPdfImportDialog.js +673 -0
- package/lib/ui/AcUiPdfImportDialog.js.map +1 -0
- package/lib/ui/AcUiPdfTextPanel.d.ts +95 -0
- package/lib/ui/AcUiPdfTextPanel.d.ts.map +1 -0
- package/lib/ui/AcUiPdfTextPanel.js +775 -0
- package/lib/ui/AcUiPdfTextPanel.js.map +1 -0
- package/package.json +11 -11
|
@@ -0,0 +1,777 @@
|
|
|
1
|
+
var __extends = (this && this.__extends) || (function () {
|
|
2
|
+
var extendStatics = function (d, b) {
|
|
3
|
+
extendStatics = Object.setPrototypeOf ||
|
|
4
|
+
({ __proto__: [] } instanceof Array && function (d, b) { d.__proto__ = b; }) ||
|
|
5
|
+
function (d, b) { for (var p in b) if (Object.prototype.hasOwnProperty.call(b, p)) d[p] = b[p]; };
|
|
6
|
+
return extendStatics(d, b);
|
|
7
|
+
};
|
|
8
|
+
return function (d, b) {
|
|
9
|
+
if (typeof b !== "function" && b !== null)
|
|
10
|
+
throw new TypeError("Class extends value " + String(b) + " is not a constructor or null");
|
|
11
|
+
extendStatics(d, b);
|
|
12
|
+
function __() { this.constructor = d; }
|
|
13
|
+
d.prototype = b === null ? Object.create(b) : (__.prototype = b.prototype, new __());
|
|
14
|
+
};
|
|
15
|
+
})();
|
|
16
|
+
var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) {
|
|
17
|
+
function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); }
|
|
18
|
+
return new (P || (P = Promise))(function (resolve, reject) {
|
|
19
|
+
function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } }
|
|
20
|
+
function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } }
|
|
21
|
+
function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); }
|
|
22
|
+
step((generator = generator.apply(thisArg, _arguments || [])).next());
|
|
23
|
+
});
|
|
24
|
+
};
|
|
25
|
+
var __generator = (this && this.__generator) || function (thisArg, body) {
|
|
26
|
+
var _ = { label: 0, sent: function() { if (t[0] & 1) throw t[1]; return t[1]; }, trys: [], ops: [] }, f, y, t, g = Object.create((typeof Iterator === "function" ? Iterator : Object).prototype);
|
|
27
|
+
return g.next = verb(0), g["throw"] = verb(1), g["return"] = verb(2), typeof Symbol === "function" && (g[Symbol.iterator] = function() { return this; }), g;
|
|
28
|
+
function verb(n) { return function (v) { return step([n, v]); }; }
|
|
29
|
+
function step(op) {
|
|
30
|
+
if (f) throw new TypeError("Generator is already executing.");
|
|
31
|
+
while (g && (g = 0, op[0] && (_ = 0)), _) try {
|
|
32
|
+
if (f = 1, y && (t = op[0] & 2 ? y["return"] : op[0] ? y["throw"] || ((t = y["return"]) && t.call(y), 0) : y.next) && !(t = t.call(y, op[1])).done) return t;
|
|
33
|
+
if (y = 0, t) op = [op[0] & 2, t.value];
|
|
34
|
+
switch (op[0]) {
|
|
35
|
+
case 0: case 1: t = op; break;
|
|
36
|
+
case 4: _.label++; return { value: op[1], done: false };
|
|
37
|
+
case 5: _.label++; y = op[1]; op = [0]; continue;
|
|
38
|
+
case 7: op = _.ops.pop(); _.trys.pop(); continue;
|
|
39
|
+
default:
|
|
40
|
+
if (!(t = _.trys, t = t.length > 0 && t[t.length - 1]) && (op[0] === 6 || op[0] === 2)) { _ = 0; continue; }
|
|
41
|
+
if (op[0] === 3 && (!t || (op[1] > t[0] && op[1] < t[3]))) { _.label = op[1]; break; }
|
|
42
|
+
if (op[0] === 6 && _.label < t[1]) { _.label = t[1]; t = op; break; }
|
|
43
|
+
if (t && _.label < t[2]) { _.label = t[2]; _.ops.push(op); break; }
|
|
44
|
+
if (t[2]) _.ops.pop();
|
|
45
|
+
_.trys.pop(); continue;
|
|
46
|
+
}
|
|
47
|
+
op = body.call(thisArg, _);
|
|
48
|
+
} catch (e) { op = [6, e]; y = 0; } finally { f = t = 0; }
|
|
49
|
+
if (op[0] & 5) throw op[1]; return { value: op[0] ? op[1] : void 0, done: true };
|
|
50
|
+
}
|
|
51
|
+
};
|
|
52
|
+
var __read = (this && this.__read) || function (o, n) {
|
|
53
|
+
var m = typeof Symbol === "function" && o[Symbol.iterator];
|
|
54
|
+
if (!m) return o;
|
|
55
|
+
var i = m.call(o), r, ar = [], e;
|
|
56
|
+
try {
|
|
57
|
+
while ((n === void 0 || n-- > 0) && !(r = i.next()).done) ar.push(r.value);
|
|
58
|
+
}
|
|
59
|
+
catch (error) { e = { error: error }; }
|
|
60
|
+
finally {
|
|
61
|
+
try {
|
|
62
|
+
if (r && !r.done && (m = i["return"])) m.call(i);
|
|
63
|
+
}
|
|
64
|
+
finally { if (e) throw e.error; }
|
|
65
|
+
}
|
|
66
|
+
return ar;
|
|
67
|
+
};
|
|
68
|
+
var __spreadArray = (this && this.__spreadArray) || function (to, from, pack) {
|
|
69
|
+
if (pack || arguments.length === 2) for (var i = 0, l = from.length, ar; i < l; i++) {
|
|
70
|
+
if (ar || !(i in from)) {
|
|
71
|
+
if (!ar) ar = Array.prototype.slice.call(from, 0, i);
|
|
72
|
+
ar[i] = from[i];
|
|
73
|
+
}
|
|
74
|
+
}
|
|
75
|
+
return to.concat(ar || Array.prototype.slice.call(from));
|
|
76
|
+
};
|
|
77
|
+
var __values = (this && this.__values) || function(o) {
|
|
78
|
+
var s = typeof Symbol === "function" && Symbol.iterator, m = s && o[s], i = 0;
|
|
79
|
+
if (m) return m.call(o);
|
|
80
|
+
if (o && typeof o.length === "number") return {
|
|
81
|
+
next: function () {
|
|
82
|
+
if (o && i >= o.length) o = void 0;
|
|
83
|
+
return { value: o && o[i++], done: !o };
|
|
84
|
+
}
|
|
85
|
+
};
|
|
86
|
+
throw new TypeError(s ? "Object is not iterable." : "Symbol.iterator is not defined.");
|
|
87
|
+
};
|
|
88
|
+
import { AcApDocManager, AcApFontUtil, AcApI18n, AcApLlmSettingsService, AcApPaletteService, AcApTextRecognitionService, acapZoomToVisible, AcEdCommand, AcEdOpenMode, resolveSelectedEntities } from '@mlightcad/cad-simple-viewer';
|
|
89
|
+
import { AcGeBox2d, AcGePoint2d } from '@mlightcad/data-model';
|
|
90
|
+
import { acapPdfT } from './acapPdfI18n';
|
|
91
|
+
import { AcApPdfTextSession } from './AcApPdfTextSession';
|
|
92
|
+
import { pdfEntityToStroke } from './pdfEntityStrokes';
|
|
93
|
+
import { clusterPdfTextStrokes } from './recognition/pdfGlyphClustering';
|
|
94
|
+
import { PdfGlyphDictionary } from './recognition/pdfGlyphDictionary';
|
|
95
|
+
import { classifyPdfTextLineFont } from './recognition/pdfTextFontKind';
|
|
96
|
+
import { AcUiPdfTextPanel } from './ui/AcUiPdfTextPanel';
|
|
97
|
+
/** `localStorage` key of the persisted glyph dictionary. */
|
|
98
|
+
export var PDF_GLYPH_STORAGE_KEY = 'mlightcad.pdftext.glyphs.v1';
|
|
99
|
+
/** Most glyph shapes kept in storage (the most recently confirmed). */
|
|
100
|
+
var PDF_GLYPH_STORAGE_LIMIT = 5000;
|
|
101
|
+
/** Height of the rendered text line image sent to a recognizer, in pixels. */
|
|
102
|
+
var OCR_IMAGE_TEXT_HEIGHT = 48;
|
|
103
|
+
/** Delay before the preview follows an edit in the panel, in ms. */
|
|
104
|
+
var PREVIEW_DELAY = 120;
|
|
105
|
+
/** Margin around a line framed in the drawing (passed to `zoomTo`). */
|
|
106
|
+
var FOCUS_MARGIN = 3;
|
|
107
|
+
/** Longest recognizer error message shown to the user. */
|
|
108
|
+
var OCR_ERROR_MESSAGE_LIMIT = 200;
|
|
109
|
+
/**
|
|
110
|
+
* `pdftext`: converts exploded text (SHX line text or outlined fonts that a
|
|
111
|
+
* PDF stores as paths) back into `AcDbText`.
|
|
112
|
+
*
|
|
113
|
+
* Workflow:
|
|
114
|
+
* 1. The user selects the strokes (a window around the text is enough;
|
|
115
|
+
* frames and other large strokes are ignored).
|
|
116
|
+
* 2. Strokes are clustered into text lines with an estimated position,
|
|
117
|
+
* height and rotation, and each line is classified as SHX line text or
|
|
118
|
+
* TrueType outline text.
|
|
119
|
+
* 3. Lines whose glyphs are all in the glyph dictionary (shapes the user
|
|
120
|
+
* already typed) are read from it.
|
|
121
|
+
* 4. All remaining lines are sent at once to OCR, when a recognizer is
|
|
122
|
+
* registered in {@link AcApTextRecognitionService}.
|
|
123
|
+
* 5. A review panel opens in the palette. Per font kind the user picks an
|
|
124
|
+
* existing text style or creates one, checks or replaces its fonts and
|
|
125
|
+
* adjusts the size; per line the user fixes or types the text. The result
|
|
126
|
+
* is previewed in the drawing. Apply converts everything in one undo step;
|
|
127
|
+
* Cancel, or closing the palette, changes nothing. Without a DOM, what
|
|
128
|
+
* was read is converted directly with the suggested styles.
|
|
129
|
+
*
|
|
130
|
+
* The dictionary is kept in `localStorage` (the 5000 most recently
|
|
131
|
+
* confirmed shapes), so later runs, on this drawing or
|
|
132
|
+
* another one using the same font, recognize more and more lines on their own.
|
|
133
|
+
*/
|
|
134
|
+
var AcApPdfTextCmd = /** @class */ (function (_super) {
|
|
135
|
+
__extends(AcApPdfTextCmd, _super);
|
|
136
|
+
function AcApPdfTextCmd() {
|
|
137
|
+
var _this = _super.call(this) || this;
|
|
138
|
+
/** Set once an OCR failure was reported in this run, so it does not nag. */
|
|
139
|
+
_this.ocrErrorShown = false;
|
|
140
|
+
_this.mode = AcEdOpenMode.Write;
|
|
141
|
+
return _this;
|
|
142
|
+
}
|
|
143
|
+
Object.defineProperty(AcApPdfTextCmd, "glyphDictionary", {
|
|
144
|
+
/**
|
|
145
|
+
* The shared glyph dictionary, loaded from `localStorage` on first use so
|
|
146
|
+
* glyphs taught in earlier sessions are recognized too.
|
|
147
|
+
*/
|
|
148
|
+
get: function () {
|
|
149
|
+
var _a;
|
|
150
|
+
if (!AcApPdfTextCmd.dictionaryLoaded) {
|
|
151
|
+
AcApPdfTextCmd.dictionaryLoaded = true;
|
|
152
|
+
try {
|
|
153
|
+
var raw = (_a = globalThis.localStorage) === null || _a === void 0 ? void 0 : _a.getItem(PDF_GLYPH_STORAGE_KEY);
|
|
154
|
+
if (raw)
|
|
155
|
+
AcApPdfTextCmd.dictionary.load(JSON.parse(raw));
|
|
156
|
+
}
|
|
157
|
+
catch (_b) {
|
|
158
|
+
// Storage unavailable or corrupt: start empty.
|
|
159
|
+
}
|
|
160
|
+
}
|
|
161
|
+
return AcApPdfTextCmd.dictionary;
|
|
162
|
+
},
|
|
163
|
+
enumerable: false,
|
|
164
|
+
configurable: true
|
|
165
|
+
});
|
|
166
|
+
AcApPdfTextCmd.saveDictionary = function () {
|
|
167
|
+
var _a;
|
|
168
|
+
try {
|
|
169
|
+
(_a = globalThis.localStorage) === null || _a === void 0 ? void 0 : _a.setItem(PDF_GLYPH_STORAGE_KEY, JSON.stringify(AcApPdfTextCmd.dictionary.toJSON(PDF_GLYPH_STORAGE_LIMIT)));
|
|
170
|
+
}
|
|
171
|
+
catch (_b) {
|
|
172
|
+
// Quota or privacy mode: the session dictionary still works.
|
|
173
|
+
}
|
|
174
|
+
};
|
|
175
|
+
AcApPdfTextCmd.prototype.execute = function (context) {
|
|
176
|
+
return __awaiter(this, void 0, void 0, function () {
|
|
177
|
+
var resolved, entityById, strokes, lines, dictionary, texts, sources, session, apply, changesExisting, fonts, measure, ready, ids, entities, _a, _b, _c, line, text;
|
|
178
|
+
var e_1, _d;
|
|
179
|
+
return __generator(this, function (_e) {
|
|
180
|
+
switch (_e.label) {
|
|
181
|
+
case 0: return [4 /*yield*/, resolveSelectedEntities(context, {
|
|
182
|
+
promptKey: 'pdftext'
|
|
183
|
+
})];
|
|
184
|
+
case 1:
|
|
185
|
+
resolved = _e.sent();
|
|
186
|
+
if (!resolved)
|
|
187
|
+
return [2 /*return*/];
|
|
188
|
+
context.view.selectionSet.clear();
|
|
189
|
+
entityById = new Map();
|
|
190
|
+
strokes = [];
|
|
191
|
+
resolved.entities.forEach(function (entity, i) {
|
|
192
|
+
var id = resolved.ids[i];
|
|
193
|
+
var stroke = pdfEntityToStroke(entity, id);
|
|
194
|
+
if (!stroke)
|
|
195
|
+
return;
|
|
196
|
+
entityById.set(id, entity);
|
|
197
|
+
strokes.push(stroke);
|
|
198
|
+
});
|
|
199
|
+
lines = clusterPdfTextStrokes(strokes).lines;
|
|
200
|
+
if (lines.length === 0) {
|
|
201
|
+
this.notify(AcApI18n.t('jig.pdftext.noCandidates'), 'warning');
|
|
202
|
+
return [2 /*return*/];
|
|
203
|
+
}
|
|
204
|
+
this.ocrErrorShown = false;
|
|
205
|
+
return [4 /*yield*/, this.hintWhenOcrUnavailable()
|
|
206
|
+
// 1. Lines whose glyphs are all known need neither OCR nor the user.
|
|
207
|
+
];
|
|
208
|
+
case 2:
|
|
209
|
+
_e.sent();
|
|
210
|
+
dictionary = AcApPdfTextCmd.glyphDictionary;
|
|
211
|
+
texts = lines.map(function (line) {
|
|
212
|
+
return dictionary.lookup(line);
|
|
213
|
+
});
|
|
214
|
+
sources = texts.map(function (text) {
|
|
215
|
+
return text ? 'dictionary' : 'unread';
|
|
216
|
+
});
|
|
217
|
+
// 2. All other lines go to OCR at once.
|
|
218
|
+
return [4 /*yield*/, this.recognizeAll(lines, texts)];
|
|
219
|
+
case 3:
|
|
220
|
+
// 2. All other lines go to OCR at once.
|
|
221
|
+
_e.sent();
|
|
222
|
+
texts.forEach(function (text, i) {
|
|
223
|
+
if (text && sources[i] === 'unread')
|
|
224
|
+
sources[i] = 'ocr';
|
|
225
|
+
});
|
|
226
|
+
session = new AcApPdfTextSession({
|
|
227
|
+
db: context.doc.database,
|
|
228
|
+
fontKind: styleFontKind,
|
|
229
|
+
rows: lines.map(function (line, i) {
|
|
230
|
+
var _a;
|
|
231
|
+
return ({
|
|
232
|
+
line: line,
|
|
233
|
+
kind: classifyPdfTextLineFont(line),
|
|
234
|
+
text: (_a = texts[i]) !== null && _a !== void 0 ? _a : '',
|
|
235
|
+
source: sources[i],
|
|
236
|
+
included: !!texts[i]
|
|
237
|
+
});
|
|
238
|
+
})
|
|
239
|
+
});
|
|
240
|
+
if (!(typeof document !== 'undefined')) return [3 /*break*/, 5];
|
|
241
|
+
return [4 /*yield*/, this.review(context, session, entityById)];
|
|
242
|
+
case 4:
|
|
243
|
+
apply = _e.sent();
|
|
244
|
+
if (!apply) {
|
|
245
|
+
session.restoreStyles();
|
|
246
|
+
this.notify(acapPdfT('jig.pdftext.cancelled'));
|
|
247
|
+
return [2 /*return*/];
|
|
248
|
+
}
|
|
249
|
+
_e.label = 5;
|
|
250
|
+
case 5:
|
|
251
|
+
changesExisting = session.kinds.some(function (kind) {
|
|
252
|
+
return session.changesExistingStyle(kind);
|
|
253
|
+
});
|
|
254
|
+
fonts = session.syncStyles();
|
|
255
|
+
return [4 /*yield*/, loadFonts(fonts)];
|
|
256
|
+
case 6:
|
|
257
|
+
_e.sent();
|
|
258
|
+
return [4 /*yield*/, prepareMeasure(fonts)];
|
|
259
|
+
case 7:
|
|
260
|
+
measure = _e.sent();
|
|
261
|
+
ready = session.readyRows;
|
|
262
|
+
ids = [];
|
|
263
|
+
entities = ready.map(function (row) {
|
|
264
|
+
ids.push.apply(ids, __spreadArray([], __read(row.line.strokes.map(function (stroke) { return stroke.id; })), false));
|
|
265
|
+
return createRowEntity(session, row, entityById, measure);
|
|
266
|
+
});
|
|
267
|
+
if (entities.length > 0) {
|
|
268
|
+
context.doc.database.tables.blockTable.modelSpace.appendEntity(entities);
|
|
269
|
+
context.doc.entityService.eraseEntities(ids);
|
|
270
|
+
}
|
|
271
|
+
// Texts that already used a style whose fonts changed must redraw.
|
|
272
|
+
if (changesExisting)
|
|
273
|
+
AcApDocManager.instance.regen();
|
|
274
|
+
try {
|
|
275
|
+
// Only text the user typed is trusted to recognize other drawings.
|
|
276
|
+
for (_a = __values(session.learnable), _b = _a.next(); !_b.done; _b = _a.next()) {
|
|
277
|
+
_c = _b.value, line = _c.line, text = _c.text;
|
|
278
|
+
dictionary.learn(line, text);
|
|
279
|
+
}
|
|
280
|
+
}
|
|
281
|
+
catch (e_1_1) { e_1 = { error: e_1_1 }; }
|
|
282
|
+
finally {
|
|
283
|
+
try {
|
|
284
|
+
if (_b && !_b.done && (_d = _a.return)) _d.call(_a);
|
|
285
|
+
}
|
|
286
|
+
finally { if (e_1) throw e_1.error; }
|
|
287
|
+
}
|
|
288
|
+
AcApPdfTextCmd.saveDictionary();
|
|
289
|
+
this.notify(acapPdfT('jig.pdftext.summary', {
|
|
290
|
+
converted: ready.length,
|
|
291
|
+
automatic: ready.filter(function (row) { return row.source !== 'typed'; }).length,
|
|
292
|
+
skipped: lines.length - ready.length
|
|
293
|
+
}));
|
|
294
|
+
return [2 /*return*/];
|
|
295
|
+
}
|
|
296
|
+
});
|
|
297
|
+
});
|
|
298
|
+
};
|
|
299
|
+
/**
|
|
300
|
+
* Shows the review panel in the palette and previews the result in the
|
|
301
|
+
* drawing until the user applies or cancels.
|
|
302
|
+
*
|
|
303
|
+
* @returns Whether the user applied.
|
|
304
|
+
*/
|
|
305
|
+
AcApPdfTextCmd.prototype.review = function (context, session, entityById) {
|
|
306
|
+
return __awaiter(this, void 0, void 0, function () {
|
|
307
|
+
var view, strokeIds, scratch, previews, focused, hidden, timer, generation, clearPreview, refreshPreview, schedulePreview, setHidden, finish, result, panel, handle;
|
|
308
|
+
var _this = this;
|
|
309
|
+
return __generator(this, function (_a) {
|
|
310
|
+
switch (_a.label) {
|
|
311
|
+
case 0:
|
|
312
|
+
view = context.view;
|
|
313
|
+
strokeIds = session.rows.flatMap(function (row) {
|
|
314
|
+
return row.line.strokes.map(function (stroke) { return stroke.id; });
|
|
315
|
+
});
|
|
316
|
+
scratch = new PdfGlyphDictionary();
|
|
317
|
+
scratch.load(AcApPdfTextCmd.glyphDictionary.toJSON());
|
|
318
|
+
previews = [];
|
|
319
|
+
focused = [];
|
|
320
|
+
hidden = false;
|
|
321
|
+
generation = 0;
|
|
322
|
+
clearPreview = function () {
|
|
323
|
+
var e_2, _a;
|
|
324
|
+
try {
|
|
325
|
+
for (var previews_1 = __values(previews), previews_1_1 = previews_1.next(); !previews_1_1.done; previews_1_1 = previews_1.next()) {
|
|
326
|
+
var text = previews_1_1.value;
|
|
327
|
+
view.removeTransientEntity(text.objectId);
|
|
328
|
+
}
|
|
329
|
+
}
|
|
330
|
+
catch (e_2_1) { e_2 = { error: e_2_1 }; }
|
|
331
|
+
finally {
|
|
332
|
+
try {
|
|
333
|
+
if (previews_1_1 && !previews_1_1.done && (_a = previews_1.return)) _a.call(previews_1);
|
|
334
|
+
}
|
|
335
|
+
finally { if (e_2) throw e_2.error; }
|
|
336
|
+
}
|
|
337
|
+
previews = [];
|
|
338
|
+
};
|
|
339
|
+
refreshPreview = function () { return __awaiter(_this, void 0, void 0, function () {
|
|
340
|
+
var current, fonts, measure;
|
|
341
|
+
return __generator(this, function (_a) {
|
|
342
|
+
switch (_a.label) {
|
|
343
|
+
case 0:
|
|
344
|
+
current = ++generation;
|
|
345
|
+
fonts = session.syncStyles();
|
|
346
|
+
return [4 /*yield*/, loadFonts(fonts)];
|
|
347
|
+
case 1:
|
|
348
|
+
_a.sent();
|
|
349
|
+
return [4 /*yield*/, prepareMeasure(fonts)
|
|
350
|
+
// A newer edit (or the end of the review) superseded this one.
|
|
351
|
+
];
|
|
352
|
+
case 2:
|
|
353
|
+
measure = _a.sent();
|
|
354
|
+
// A newer edit (or the end of the review) superseded this one.
|
|
355
|
+
if (current !== generation)
|
|
356
|
+
return [2 /*return*/];
|
|
357
|
+
// Merging measures text too: gaps become spaces in the chosen fonts.
|
|
358
|
+
session.setMeasurer(measure);
|
|
359
|
+
clearPreview();
|
|
360
|
+
previews = session.readyRows.map(function (row) {
|
|
361
|
+
return createRowEntity(session, row, entityById, measure);
|
|
362
|
+
});
|
|
363
|
+
if (previews.length > 0)
|
|
364
|
+
view.addTransientEntity(previews);
|
|
365
|
+
return [2 /*return*/];
|
|
366
|
+
}
|
|
367
|
+
});
|
|
368
|
+
}); };
|
|
369
|
+
schedulePreview = function () {
|
|
370
|
+
if (timer)
|
|
371
|
+
clearTimeout(timer);
|
|
372
|
+
timer = setTimeout(function () {
|
|
373
|
+
timer = undefined;
|
|
374
|
+
void refreshPreview();
|
|
375
|
+
}, PREVIEW_DELAY);
|
|
376
|
+
};
|
|
377
|
+
setHidden = function (hide) {
|
|
378
|
+
var e_3, _a;
|
|
379
|
+
hidden = hide;
|
|
380
|
+
try {
|
|
381
|
+
for (var strokeIds_1 = __values(strokeIds), strokeIds_1_1 = strokeIds_1.next(); !strokeIds_1_1.done; strokeIds_1_1 = strokeIds_1.next()) {
|
|
382
|
+
var id = strokeIds_1_1.value;
|
|
383
|
+
view.setEntitySceneVisible(id, !hide);
|
|
384
|
+
}
|
|
385
|
+
}
|
|
386
|
+
catch (e_3_1) { e_3 = { error: e_3_1 }; }
|
|
387
|
+
finally {
|
|
388
|
+
try {
|
|
389
|
+
if (strokeIds_1_1 && !strokeIds_1_1.done && (_a = strokeIds_1.return)) _a.call(strokeIds_1);
|
|
390
|
+
}
|
|
391
|
+
finally { if (e_3) throw e_3.error; }
|
|
392
|
+
}
|
|
393
|
+
};
|
|
394
|
+
finish = function () { };
|
|
395
|
+
result = new Promise(function (resolve) {
|
|
396
|
+
finish = resolve;
|
|
397
|
+
});
|
|
398
|
+
panel = new AcUiPdfTextPanel({
|
|
399
|
+
session: session,
|
|
400
|
+
fonts: AcApDocManager.instance.avaiableFonts,
|
|
401
|
+
replacementFont: function (font) { return AcApFontUtil.getReplacementFontName(font); },
|
|
402
|
+
onChange: schedulePreview,
|
|
403
|
+
onFocusRows: function (rows, zoom) {
|
|
404
|
+
if (focused.length > 0)
|
|
405
|
+
view.unhighlight(focused);
|
|
406
|
+
var lines = rows.map(function (row) { return row.line; });
|
|
407
|
+
focused = lines.flatMap(function (line) { return line.strokes.map(function (stroke) { return stroke.id; }); });
|
|
408
|
+
if (focused.length > 0)
|
|
409
|
+
view.highlight(focused);
|
|
410
|
+
var box = zoom ? linesBox(lines) : undefined;
|
|
411
|
+
if (box) {
|
|
412
|
+
acapZoomToVisible(view, box, FOCUS_MARGIN, handle.coveredInsets(view.canvas));
|
|
413
|
+
}
|
|
414
|
+
},
|
|
415
|
+
onCommitRow: function (index) {
|
|
416
|
+
var e_4, _a;
|
|
417
|
+
var row = session.rows[index];
|
|
418
|
+
if (!row)
|
|
419
|
+
return [];
|
|
420
|
+
try {
|
|
421
|
+
for (var _b = __values(session.learnableOf(row)), _c = _b.next(); !_c.done; _c = _b.next()) {
|
|
422
|
+
var _d = _c.value, line = _d.line, text = _d.text;
|
|
423
|
+
scratch.learn(line, text);
|
|
424
|
+
}
|
|
425
|
+
}
|
|
426
|
+
catch (e_4_1) { e_4 = { error: e_4_1 }; }
|
|
427
|
+
finally {
|
|
428
|
+
try {
|
|
429
|
+
if (_c && !_c.done && (_a = _b.return)) _a.call(_b);
|
|
430
|
+
}
|
|
431
|
+
finally { if (e_4) throw e_4.error; }
|
|
432
|
+
}
|
|
433
|
+
return session.fillUnread(function (line) { return scratch.lookup(line); });
|
|
434
|
+
},
|
|
435
|
+
onHideStrokes: setHidden,
|
|
436
|
+
onClose: function (apply) { return finish(apply); }
|
|
437
|
+
});
|
|
438
|
+
handle = AcApPaletteService.open({
|
|
439
|
+
id: 'pdftext',
|
|
440
|
+
title: acapPdfT('jig.pdftext.panel.title'),
|
|
441
|
+
element: panel.element
|
|
442
|
+
}, { container: view.container });
|
|
443
|
+
handle.onClosed(function () { return finish(false); });
|
|
444
|
+
_a.label = 1;
|
|
445
|
+
case 1:
|
|
446
|
+
_a.trys.push([1, , 4, 5]);
|
|
447
|
+
return [4 /*yield*/, refreshPreview()];
|
|
448
|
+
case 2:
|
|
449
|
+
_a.sent();
|
|
450
|
+
panel.focusFirstUnread();
|
|
451
|
+
return [4 /*yield*/, result];
|
|
452
|
+
case 3: return [2 /*return*/, _a.sent()];
|
|
453
|
+
case 4:
|
|
454
|
+
if (timer)
|
|
455
|
+
clearTimeout(timer);
|
|
456
|
+
generation++;
|
|
457
|
+
clearPreview();
|
|
458
|
+
if (hidden)
|
|
459
|
+
setHidden(false);
|
|
460
|
+
if (focused.length > 0)
|
|
461
|
+
view.unhighlight(focused);
|
|
462
|
+
handle.close();
|
|
463
|
+
panel.destroy();
|
|
464
|
+
return [7 /*endfinally*/];
|
|
465
|
+
case 5: return [2 /*return*/];
|
|
466
|
+
}
|
|
467
|
+
});
|
|
468
|
+
});
|
|
469
|
+
};
|
|
470
|
+
/**
|
|
471
|
+
* Sends every line `texts` has no entry for to OCR in one batch, behind the
|
|
472
|
+
* busy indicator, and fills `texts` in place.
|
|
473
|
+
*
|
|
474
|
+
* OCR answers are not taught to the glyph dictionary: only text the user
|
|
475
|
+
* typed is trusted to recognize other drawings.
|
|
476
|
+
*
|
|
477
|
+
* @returns How many lines OCR read.
|
|
478
|
+
*/
|
|
479
|
+
AcApPdfTextCmd.prototype.recognizeAll = function (lines, texts) {
|
|
480
|
+
return __awaiter(this, void 0, void 0, function () {
|
|
481
|
+
var pending, images, results, recognized;
|
|
482
|
+
var _this = this;
|
|
483
|
+
return __generator(this, function (_a) {
|
|
484
|
+
switch (_a.label) {
|
|
485
|
+
case 0:
|
|
486
|
+
if (!AcApTextRecognitionService.hasRecognizer)
|
|
487
|
+
return [2 /*return*/, 0];
|
|
488
|
+
pending = [];
|
|
489
|
+
images = [];
|
|
490
|
+
lines.forEach(function (line, i) {
|
|
491
|
+
if (texts[i])
|
|
492
|
+
return;
|
|
493
|
+
var image = renderLineImage(line);
|
|
494
|
+
if (!image)
|
|
495
|
+
return;
|
|
496
|
+
pending.push(i);
|
|
497
|
+
images.push(image);
|
|
498
|
+
});
|
|
499
|
+
if (images.length === 0)
|
|
500
|
+
return [2 /*return*/, 0];
|
|
501
|
+
return [4 /*yield*/, AcApDocManager.instance.withBusyIndicator(function () {
|
|
502
|
+
return AcApTextRecognitionService.recognizeBatch({ images: images, locale: AcApI18n.currentLocale }, { onError: function (error) { return _this.reportOcrError(error); } });
|
|
503
|
+
}, acapPdfT('jig.pdftext.recognizing', { count: images.length }))];
|
|
504
|
+
case 1:
|
|
505
|
+
results = _a.sent();
|
|
506
|
+
recognized = 0;
|
|
507
|
+
pending.forEach(function (lineIndex, i) {
|
|
508
|
+
if (!results[i])
|
|
509
|
+
return;
|
|
510
|
+
texts[lineIndex] = results[i];
|
|
511
|
+
recognized++;
|
|
512
|
+
});
|
|
513
|
+
return [2 /*return*/, recognized];
|
|
514
|
+
}
|
|
515
|
+
});
|
|
516
|
+
});
|
|
517
|
+
};
|
|
518
|
+
/**
|
|
519
|
+
* Tells the user once per session how to turn on OCR suggestions when the
|
|
520
|
+
* shared AI model settings report no image-capable model.
|
|
521
|
+
*/
|
|
522
|
+
AcApPdfTextCmd.prototype.hintWhenOcrUnavailable = function () {
|
|
523
|
+
return __awaiter(this, void 0, void 0, function () {
|
|
524
|
+
var status;
|
|
525
|
+
return __generator(this, function (_a) {
|
|
526
|
+
switch (_a.label) {
|
|
527
|
+
case 0:
|
|
528
|
+
if (AcApPdfTextCmd.ocrHintShown)
|
|
529
|
+
return [2 /*return*/];
|
|
530
|
+
return [4 /*yield*/, AcApLlmSettingsService.getStatus()];
|
|
531
|
+
case 1:
|
|
532
|
+
status = _a.sent();
|
|
533
|
+
if (!status || status.vision)
|
|
534
|
+
return [2 /*return*/];
|
|
535
|
+
AcApPdfTextCmd.ocrHintShown = true;
|
|
536
|
+
this.notify(AcApI18n.t('jig.pdftext.ocrNotConfigured'));
|
|
537
|
+
return [2 /*return*/];
|
|
538
|
+
}
|
|
539
|
+
});
|
|
540
|
+
});
|
|
541
|
+
};
|
|
542
|
+
/**
|
|
543
|
+
* Tells the user, once per run, why no suggestion came (bad API key,
|
|
544
|
+
* network, quota, ...) instead of leaving unexplained unread lines.
|
|
545
|
+
*/
|
|
546
|
+
AcApPdfTextCmd.prototype.reportOcrError = function (error) {
|
|
547
|
+
console.warn('[pdftext] Text recognition failed:', error);
|
|
548
|
+
if (this.ocrErrorShown)
|
|
549
|
+
return;
|
|
550
|
+
this.ocrErrorShown = true;
|
|
551
|
+
this.notify(acapPdfT('jig.pdftext.ocrFailed', { message: ocrErrorMessage(error) }), 'error');
|
|
552
|
+
};
|
|
553
|
+
AcApPdfTextCmd.dictionary = new PdfGlyphDictionary();
|
|
554
|
+
AcApPdfTextCmd.dictionaryLoaded = false;
|
|
555
|
+
/** Set once the "OCR is off" hint was shown, so it does not nag. */
|
|
556
|
+
AcApPdfTextCmd.ocrHintShown = false;
|
|
557
|
+
return AcApPdfTextCmd;
|
|
558
|
+
}(AcEdCommand));
|
|
559
|
+
export { AcApPdfTextCmd };
|
|
560
|
+
/**
|
|
561
|
+
* The TEXT (or MTEXT for merged rows) of a row, on the layer and in the
|
|
562
|
+
* colour of its strokes.
|
|
563
|
+
*/
|
|
564
|
+
function createRowEntity(session, row, entityById, measure) {
|
|
565
|
+
var _a;
|
|
566
|
+
var text = session.createEntity(row, measure);
|
|
567
|
+
var source = entityById.get((_a = row.line.strokes[0]) === null || _a === void 0 ? void 0 : _a.id);
|
|
568
|
+
if (source) {
|
|
569
|
+
text.layer = source.layer;
|
|
570
|
+
text.color = source.color.clone();
|
|
571
|
+
}
|
|
572
|
+
return text;
|
|
573
|
+
}
|
|
574
|
+
/** Loads the catalog fonts in `fonts` that are not loaded yet. */
|
|
575
|
+
function loadFonts(fonts) {
|
|
576
|
+
return __awaiter(this, void 0, void 0, function () {
|
|
577
|
+
var missing, error_1;
|
|
578
|
+
return __generator(this, function (_a) {
|
|
579
|
+
switch (_a.label) {
|
|
580
|
+
case 0:
|
|
581
|
+
missing = fonts.filter(function (font) {
|
|
582
|
+
return AcApFontUtil.findFontInfoByName(font) && !AcApFontUtil.isFontLoaded(font);
|
|
583
|
+
});
|
|
584
|
+
if (missing.length === 0)
|
|
585
|
+
return [2 /*return*/];
|
|
586
|
+
_a.label = 1;
|
|
587
|
+
case 1:
|
|
588
|
+
_a.trys.push([1, 3, , 4]);
|
|
589
|
+
return [4 /*yield*/, AcApDocManager.instance.loadFonts(missing)];
|
|
590
|
+
case 2:
|
|
591
|
+
_a.sent();
|
|
592
|
+
return [3 /*break*/, 4];
|
|
593
|
+
case 3:
|
|
594
|
+
error_1 = _a.sent();
|
|
595
|
+
// Texts still draw with fallback fonts once these load later.
|
|
596
|
+
console.warn('[pdftext] Could not load text style fonts:', error_1);
|
|
597
|
+
return [3 /*break*/, 4];
|
|
598
|
+
case 4: return [2 /*return*/];
|
|
599
|
+
}
|
|
600
|
+
});
|
|
601
|
+
});
|
|
602
|
+
}
|
|
603
|
+
/**
|
|
604
|
+
* Loads what width measuring needs and returns the measurer, or `undefined`
|
|
605
|
+
* when the fonts cannot be loaded (the width factor then stays 1).
|
|
606
|
+
*/
|
|
607
|
+
function prepareMeasure(fonts) {
|
|
608
|
+
return __awaiter(this, void 0, void 0, function () {
|
|
609
|
+
var error_2;
|
|
610
|
+
return __generator(this, function (_a) {
|
|
611
|
+
switch (_a.label) {
|
|
612
|
+
case 0:
|
|
613
|
+
_a.trys.push([0, 2, , 3]);
|
|
614
|
+
return [4 /*yield*/, AcApFontUtil.prepareTextMeasurement(fonts)];
|
|
615
|
+
case 1:
|
|
616
|
+
_a.sent();
|
|
617
|
+
return [3 /*break*/, 3];
|
|
618
|
+
case 2:
|
|
619
|
+
error_2 = _a.sent();
|
|
620
|
+
console.warn('[pdftext] Could not load fonts to fit text widths:', error_2);
|
|
621
|
+
return [2 /*return*/, undefined];
|
|
622
|
+
case 3: return [2 /*return*/, function (text, font, height, bigFont) {
|
|
623
|
+
return AcApFontUtil.measureTextWidth(text, font, height, bigFont || undefined);
|
|
624
|
+
}];
|
|
625
|
+
}
|
|
626
|
+
});
|
|
627
|
+
});
|
|
628
|
+
}
|
|
629
|
+
/** World box around the strokes of lines. */
|
|
630
|
+
function linesBox(lines) {
|
|
631
|
+
var e_5, _a, e_6, _b;
|
|
632
|
+
var minX = Infinity;
|
|
633
|
+
var minY = Infinity;
|
|
634
|
+
var maxX = -Infinity;
|
|
635
|
+
var maxY = -Infinity;
|
|
636
|
+
try {
|
|
637
|
+
for (var _c = __values(lines.flatMap(function (line) { return line.strokes; })), _d = _c.next(); !_d.done; _d = _c.next()) {
|
|
638
|
+
var stroke = _d.value;
|
|
639
|
+
try {
|
|
640
|
+
for (var _e = (e_6 = void 0, __values(stroke.points)), _f = _e.next(); !_f.done; _f = _e.next()) {
|
|
641
|
+
var p = _f.value;
|
|
642
|
+
minX = Math.min(minX, p.x);
|
|
643
|
+
minY = Math.min(minY, p.y);
|
|
644
|
+
maxX = Math.max(maxX, p.x);
|
|
645
|
+
maxY = Math.max(maxY, p.y);
|
|
646
|
+
}
|
|
647
|
+
}
|
|
648
|
+
catch (e_6_1) { e_6 = { error: e_6_1 }; }
|
|
649
|
+
finally {
|
|
650
|
+
try {
|
|
651
|
+
if (_f && !_f.done && (_b = _e.return)) _b.call(_e);
|
|
652
|
+
}
|
|
653
|
+
finally { if (e_6) throw e_6.error; }
|
|
654
|
+
}
|
|
655
|
+
}
|
|
656
|
+
}
|
|
657
|
+
catch (e_5_1) { e_5 = { error: e_5_1 }; }
|
|
658
|
+
finally {
|
|
659
|
+
try {
|
|
660
|
+
if (_d && !_d.done && (_a = _c.return)) _a.call(_c);
|
|
661
|
+
}
|
|
662
|
+
finally { if (e_5) throw e_5.error; }
|
|
663
|
+
}
|
|
664
|
+
if (!Number.isFinite(minX))
|
|
665
|
+
return undefined;
|
|
666
|
+
return new AcGeBox2d(new AcGePoint2d(minX, minY), new AcGePoint2d(maxX, maxY));
|
|
667
|
+
}
|
|
668
|
+
/**
|
|
669
|
+
* Engine the viewer draws a style font with: the loaded font's own type,
|
|
670
|
+
* else the font catalog's, else that of the font substituted for a missing
|
|
671
|
+
* one (e.g. a `Standard` style without a known font draws in `simsun`).
|
|
672
|
+
*/
|
|
673
|
+
function styleFontKind(font) {
|
|
674
|
+
var _a, _b;
|
|
675
|
+
if (!font)
|
|
676
|
+
return undefined;
|
|
677
|
+
var direct = (_a = AcApFontUtil.getFontType(font)) !== null && _a !== void 0 ? _a : AcApFontUtil.getCatalogFontType(font);
|
|
678
|
+
if (direct)
|
|
679
|
+
return direct;
|
|
680
|
+
var replacement = AcApFontUtil.getReplacementFontName(font);
|
|
681
|
+
if (!replacement || replacement === font)
|
|
682
|
+
return undefined;
|
|
683
|
+
return ((_b = AcApFontUtil.getFontType(replacement)) !== null && _b !== void 0 ? _b : AcApFontUtil.getCatalogFontType(replacement));
|
|
684
|
+
}
|
|
685
|
+
/** One-line, length-limited description of a recognizer error. */
|
|
686
|
+
function ocrErrorMessage(error) {
|
|
687
|
+
var raw = error instanceof Error ? error.message : String(error !== null && error !== void 0 ? error : 'unknown error');
|
|
688
|
+
var text = raw.replace(/\s+/g, ' ').trim() || String(error);
|
|
689
|
+
return text.length > OCR_ERROR_MESSAGE_LIMIT
|
|
690
|
+
? "".concat(text.slice(0, OCR_ERROR_MESSAGE_LIMIT - 1), "\u2026")
|
|
691
|
+
: text;
|
|
692
|
+
}
|
|
693
|
+
/**
|
|
694
|
+
* Renders a text line upright, dark on white, as a PNG data URL for OCR.
|
|
695
|
+
*
|
|
696
|
+
* @returns The data URL, or `undefined` outside a browser.
|
|
697
|
+
*/
|
|
698
|
+
function renderLineImage(line) {
|
|
699
|
+
var e_7, _a, e_8, _b, e_9, _c;
|
|
700
|
+
if (typeof document === 'undefined')
|
|
701
|
+
return undefined;
|
|
702
|
+
var scale = OCR_IMAGE_TEXT_HEIGHT / line.height;
|
|
703
|
+
var pad = OCR_IMAGE_TEXT_HEIGHT * 0.5;
|
|
704
|
+
var c = Math.cos(line.rotation);
|
|
705
|
+
var s = Math.sin(line.rotation);
|
|
706
|
+
var local = function (x, y) {
|
|
707
|
+
var dx = x - line.position.x;
|
|
708
|
+
var dy = y - line.position.y;
|
|
709
|
+
return { u: dx * c + dy * s, v: -dx * s + dy * c };
|
|
710
|
+
};
|
|
711
|
+
var minV = 0;
|
|
712
|
+
var maxV = line.height;
|
|
713
|
+
try {
|
|
714
|
+
for (var _d = __values(line.strokes), _e = _d.next(); !_e.done; _e = _d.next()) {
|
|
715
|
+
var stroke = _e.value;
|
|
716
|
+
try {
|
|
717
|
+
for (var _f = (e_8 = void 0, __values(stroke.points)), _g = _f.next(); !_g.done; _g = _f.next()) {
|
|
718
|
+
var p = _g.value;
|
|
719
|
+
var v = local(p.x, p.y).v;
|
|
720
|
+
minV = Math.min(minV, v);
|
|
721
|
+
maxV = Math.max(maxV, v);
|
|
722
|
+
}
|
|
723
|
+
}
|
|
724
|
+
catch (e_8_1) { e_8 = { error: e_8_1 }; }
|
|
725
|
+
finally {
|
|
726
|
+
try {
|
|
727
|
+
if (_g && !_g.done && (_b = _f.return)) _b.call(_f);
|
|
728
|
+
}
|
|
729
|
+
finally { if (e_8) throw e_8.error; }
|
|
730
|
+
}
|
|
731
|
+
}
|
|
732
|
+
}
|
|
733
|
+
catch (e_7_1) { e_7 = { error: e_7_1 }; }
|
|
734
|
+
finally {
|
|
735
|
+
try {
|
|
736
|
+
if (_e && !_e.done && (_a = _d.return)) _a.call(_d);
|
|
737
|
+
}
|
|
738
|
+
finally { if (e_7) throw e_7.error; }
|
|
739
|
+
}
|
|
740
|
+
var canvas = document.createElement('canvas');
|
|
741
|
+
canvas.width = Math.ceil(line.width * scale + pad * 2);
|
|
742
|
+
canvas.height = Math.ceil((maxV - minV) * scale + pad * 2);
|
|
743
|
+
var g = canvas.getContext('2d');
|
|
744
|
+
if (!g)
|
|
745
|
+
return undefined;
|
|
746
|
+
g.fillStyle = '#ffffff';
|
|
747
|
+
g.fillRect(0, 0, canvas.width, canvas.height);
|
|
748
|
+
g.strokeStyle = '#000000';
|
|
749
|
+
g.lineWidth = Math.max(1.5, OCR_IMAGE_TEXT_HEIGHT / 16);
|
|
750
|
+
g.lineCap = 'round';
|
|
751
|
+
g.lineJoin = 'round';
|
|
752
|
+
try {
|
|
753
|
+
for (var _h = __values(line.strokes), _j = _h.next(); !_j.done; _j = _h.next()) {
|
|
754
|
+
var stroke = _j.value;
|
|
755
|
+
g.beginPath();
|
|
756
|
+
stroke.points.forEach(function (p, i) {
|
|
757
|
+
var _a = local(p.x, p.y), u = _a.u, v = _a.v;
|
|
758
|
+
var px = pad + u * scale;
|
|
759
|
+
var py = pad + (maxV - v) * scale;
|
|
760
|
+
if (i === 0)
|
|
761
|
+
g.moveTo(px, py);
|
|
762
|
+
else
|
|
763
|
+
g.lineTo(px, py);
|
|
764
|
+
});
|
|
765
|
+
g.stroke();
|
|
766
|
+
}
|
|
767
|
+
}
|
|
768
|
+
catch (e_9_1) { e_9 = { error: e_9_1 }; }
|
|
769
|
+
finally {
|
|
770
|
+
try {
|
|
771
|
+
if (_j && !_j.done && (_c = _h.return)) _c.call(_h);
|
|
772
|
+
}
|
|
773
|
+
finally { if (e_9) throw e_9.error; }
|
|
774
|
+
}
|
|
775
|
+
return canvas.toDataURL('image/png');
|
|
776
|
+
}
|
|
777
|
+
//# sourceMappingURL=AcApPdfTextCmd.js.map
|