@mlightcad/cad-pdf-plugin 1.8.0-preview.3 → 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.
Files changed (189) hide show
  1. package/LICENSE +21 -21
  2. package/README.md +280 -186
  3. package/dist/cad-pdf-plugin-register.js +29 -11
  4. package/dist/cad-pdf-plugin-register.umd.cjs +1 -1
  5. package/dist/cad-pdf-plugin.js +17568 -8428
  6. package/dist/cad-pdf-plugin.umd.cjs +847 -13
  7. package/lib/AcApConvertToPdfCmd.d.ts.map +1 -1
  8. package/lib/AcApConvertToPdfCmd.js +14 -3
  9. package/lib/AcApConvertToPdfCmd.js.map +1 -1
  10. package/lib/AcApImportPdfCmd.d.ts +5 -3
  11. package/lib/AcApImportPdfCmd.d.ts.map +1 -1
  12. package/lib/AcApImportPdfCmd.js +5 -3
  13. package/lib/AcApImportPdfCmd.js.map +1 -1
  14. package/lib/AcApImportPdfPromptCmd.d.ts +16 -0
  15. package/lib/AcApImportPdfPromptCmd.d.ts.map +1 -0
  16. package/lib/AcApImportPdfPromptCmd.js +89 -0
  17. package/lib/AcApImportPdfPromptCmd.js.map +1 -0
  18. package/lib/AcApPdfBlockCmd.d.ts +15 -0
  19. package/lib/AcApPdfBlockCmd.d.ts.map +1 -0
  20. package/lib/AcApPdfBlockCmd.js +75 -0
  21. package/lib/AcApPdfBlockCmd.js.map +1 -0
  22. package/lib/AcApPdfDimCmd.d.ts +20 -0
  23. package/lib/AcApPdfDimCmd.d.ts.map +1 -0
  24. package/lib/AcApPdfDimCmd.js +413 -0
  25. package/lib/AcApPdfDimCmd.js.map +1 -0
  26. package/lib/AcApPdfDimSession.d.ts +82 -0
  27. package/lib/AcApPdfDimSession.d.ts.map +1 -0
  28. package/lib/AcApPdfDimSession.js +252 -0
  29. package/lib/AcApPdfDimSession.js.map +1 -0
  30. package/lib/AcApPdfFontResolver.d.ts.map +1 -1
  31. package/lib/AcApPdfFontResolver.js +2 -5
  32. package/lib/AcApPdfFontResolver.js.map +1 -1
  33. package/lib/AcApPdfHatchCmd.d.ts +33 -0
  34. package/lib/AcApPdfHatchCmd.d.ts.map +1 -0
  35. package/lib/AcApPdfHatchCmd.js +411 -0
  36. package/lib/AcApPdfHatchCmd.js.map +1 -0
  37. package/lib/AcApPdfHatchSession.d.ts +122 -0
  38. package/lib/AcApPdfHatchSession.d.ts.map +1 -0
  39. package/lib/AcApPdfHatchSession.js +357 -0
  40. package/lib/AcApPdfHatchSession.js.map +1 -0
  41. package/lib/AcApPdfImportConvertor.d.ts +47 -5
  42. package/lib/AcApPdfImportConvertor.d.ts.map +1 -1
  43. package/lib/AcApPdfImportConvertor.js +999 -108
  44. package/lib/AcApPdfImportConvertor.js.map +1 -1
  45. package/lib/AcApPdfImportOptions.d.ts +116 -0
  46. package/lib/AcApPdfImportOptions.d.ts.map +1 -0
  47. package/lib/AcApPdfImportOptions.js +31 -0
  48. package/lib/AcApPdfImportOptions.js.map +1 -0
  49. package/lib/AcApPdfImportResources.d.ts +41 -0
  50. package/lib/AcApPdfImportResources.d.ts.map +1 -0
  51. package/lib/AcApPdfImportResources.js +52 -0
  52. package/lib/AcApPdfImportResources.js.map +1 -0
  53. package/lib/AcApPdfPlugin.d.ts +3 -3
  54. package/lib/AcApPdfPlugin.d.ts.map +1 -1
  55. package/lib/AcApPdfPlugin.js +23 -5
  56. package/lib/AcApPdfPlugin.js.map +1 -1
  57. package/lib/AcApPdfScaleCmd.d.ts +22 -0
  58. package/lib/AcApPdfScaleCmd.d.ts.map +1 -0
  59. package/lib/AcApPdfScaleCmd.js +185 -0
  60. package/lib/AcApPdfScaleCmd.js.map +1 -0
  61. package/lib/AcApPdfTextCmd.d.ts +73 -0
  62. package/lib/AcApPdfTextCmd.d.ts.map +1 -0
  63. package/lib/AcApPdfTextCmd.js +777 -0
  64. package/lib/AcApPdfTextCmd.js.map +1 -0
  65. package/lib/AcApPdfTextSession.d.ts +232 -0
  66. package/lib/AcApPdfTextSession.d.ts.map +1 -0
  67. package/lib/AcApPdfTextSession.js +826 -0
  68. package/lib/AcApPdfTextSession.js.map +1 -0
  69. package/lib/acapPdfI18n.d.ts +11 -0
  70. package/lib/acapPdfI18n.d.ts.map +1 -0
  71. package/lib/acapPdfI18n.js +57 -0
  72. package/lib/acapPdfI18n.js.map +1 -0
  73. package/lib/acapPdfPrompts.d.ts +12 -0
  74. package/lib/acapPdfPrompts.d.ts.map +1 -0
  75. package/lib/acapPdfPrompts.js +100 -0
  76. package/lib/acapPdfPrompts.js.map +1 -0
  77. package/lib/index.d.ts +28 -0
  78. package/lib/index.d.ts.map +1 -1
  79. package/lib/index.js +28 -0
  80. package/lib/index.js.map +1 -1
  81. package/lib/pdfDeprecatedMatching.d.ts +27 -0
  82. package/lib/pdfDeprecatedMatching.d.ts.map +1 -0
  83. package/lib/pdfDeprecatedMatching.js +20 -0
  84. package/lib/pdfDeprecatedMatching.js.map +1 -0
  85. package/lib/pdfDimStrokeTexts.d.ts +55 -0
  86. package/lib/pdfDimStrokeTexts.d.ts.map +1 -0
  87. package/lib/pdfDimStrokeTexts.js +274 -0
  88. package/lib/pdfDimStrokeTexts.js.map +1 -0
  89. package/lib/pdfDimensionConvert.d.ts +80 -0
  90. package/lib/pdfDimensionConvert.d.ts.map +1 -0
  91. package/lib/pdfDimensionConvert.js +566 -0
  92. package/lib/pdfDimensionConvert.js.map +1 -0
  93. package/lib/pdfEntityStrokes.d.ts +13 -0
  94. package/lib/pdfEntityStrokes.d.ts.map +1 -0
  95. package/lib/pdfEntityStrokes.js +86 -0
  96. package/lib/pdfEntityStrokes.js.map +1 -0
  97. package/lib/pdfHatchRecover.d.ts +57 -0
  98. package/lib/pdfHatchRecover.d.ts.map +1 -0
  99. package/lib/pdfHatchRecover.js +315 -0
  100. package/lib/pdfHatchRecover.js.map +1 -0
  101. package/lib/pdfImportAppend.d.ts +24 -0
  102. package/lib/pdfImportAppend.d.ts.map +1 -0
  103. package/lib/pdfImportAppend.js +35 -0
  104. package/lib/pdfImportAppend.js.map +1 -0
  105. package/lib/pdfImportEntities.d.ts +63 -0
  106. package/lib/pdfImportEntities.d.ts.map +1 -0
  107. package/lib/pdfImportEntities.js +307 -0
  108. package/lib/pdfImportEntities.js.map +1 -0
  109. package/lib/pdfImportImages.d.ts +90 -0
  110. package/lib/pdfImportImages.d.ts.map +1 -0
  111. package/lib/pdfImportImages.js +294 -0
  112. package/lib/pdfImportImages.js.map +1 -0
  113. package/lib/pdfImportShapes.d.ts +63 -0
  114. package/lib/pdfImportShapes.d.ts.map +1 -0
  115. package/lib/pdfImportShapes.js +248 -0
  116. package/lib/pdfImportShapes.js.map +1 -0
  117. package/lib/pdfVectorImport.d.ts +218 -5
  118. package/lib/pdfVectorImport.d.ts.map +1 -1
  119. package/lib/pdfVectorImport.js +566 -98
  120. package/lib/pdfVectorImport.js.map +1 -1
  121. package/lib/recognition/pdfCurveRecognition.d.ts +91 -0
  122. package/lib/recognition/pdfCurveRecognition.d.ts.map +1 -0
  123. package/lib/recognition/pdfCurveRecognition.js +506 -0
  124. package/lib/recognition/pdfCurveRecognition.js.map +1 -0
  125. package/lib/recognition/pdfDimDigitRecognition.d.ts +18 -0
  126. package/lib/recognition/pdfDimDigitRecognition.d.ts.map +1 -0
  127. package/lib/recognition/pdfDimDigitRecognition.js +520 -0
  128. package/lib/recognition/pdfDimDigitRecognition.js.map +1 -0
  129. package/lib/recognition/pdfDimensionPattern.d.ts +173 -0
  130. package/lib/recognition/pdfDimensionPattern.d.ts.map +1 -0
  131. package/lib/recognition/pdfDimensionPattern.js +1023 -0
  132. package/lib/recognition/pdfDimensionPattern.js.map +1 -0
  133. package/lib/recognition/pdfFormBlocks.d.ts +58 -0
  134. package/lib/recognition/pdfFormBlocks.d.ts.map +1 -0
  135. package/lib/recognition/pdfFormBlocks.js +260 -0
  136. package/lib/recognition/pdfFormBlocks.js.map +1 -0
  137. package/lib/recognition/pdfGlyphClustering.d.ts +81 -0
  138. package/lib/recognition/pdfGlyphClustering.d.ts.map +1 -0
  139. package/lib/recognition/pdfGlyphClustering.js +1005 -0
  140. package/lib/recognition/pdfGlyphClustering.js.map +1 -0
  141. package/lib/recognition/pdfGlyphDictionary.d.ts +49 -0
  142. package/lib/recognition/pdfGlyphDictionary.d.ts.map +1 -0
  143. package/lib/recognition/pdfGlyphDictionary.js +188 -0
  144. package/lib/recognition/pdfGlyphDictionary.js.map +1 -0
  145. package/lib/recognition/pdfHatchFaces.d.ts +84 -0
  146. package/lib/recognition/pdfHatchFaces.d.ts.map +1 -0
  147. package/lib/recognition/pdfHatchFaces.js +1285 -0
  148. package/lib/recognition/pdfHatchFaces.js.map +1 -0
  149. package/lib/recognition/pdfHatchRecognition.d.ts +222 -0
  150. package/lib/recognition/pdfHatchRecognition.d.ts.map +1 -0
  151. package/lib/recognition/pdfHatchRecognition.js +3781 -0
  152. package/lib/recognition/pdfHatchRecognition.js.map +1 -0
  153. package/lib/recognition/pdfRecGeometry.d.ts +67 -0
  154. package/lib/recognition/pdfRecGeometry.d.ts.map +1 -0
  155. package/lib/recognition/pdfRecGeometry.js +365 -0
  156. package/lib/recognition/pdfRecGeometry.js.map +1 -0
  157. package/lib/recognition/pdfTextFontKind.d.ts +16 -0
  158. package/lib/recognition/pdfTextFontKind.d.ts.map +1 -0
  159. package/lib/recognition/pdfTextFontKind.js +51 -0
  160. package/lib/recognition/pdfTextFontKind.js.map +1 -0
  161. package/lib/recognition/pdfTextMerge.d.ts +71 -0
  162. package/lib/recognition/pdfTextMerge.d.ts.map +1 -0
  163. package/lib/recognition/pdfTextMerge.js +382 -0
  164. package/lib/recognition/pdfTextMerge.js.map +1 -0
  165. package/lib/recognition/pdfTextRunMerge.d.ts +28 -0
  166. package/lib/recognition/pdfTextRunMerge.d.ts.map +1 -0
  167. package/lib/recognition/pdfTextRunMerge.js +90 -0
  168. package/lib/recognition/pdfTextRunMerge.js.map +1 -0
  169. package/lib/register.d.ts +8 -2
  170. package/lib/register.d.ts.map +1 -1
  171. package/lib/register.js +29 -4
  172. package/lib/register.js.map +1 -1
  173. package/lib/ui/AcUiPdfDimPanel.d.ts +55 -0
  174. package/lib/ui/AcUiPdfDimPanel.d.ts.map +1 -0
  175. package/lib/ui/AcUiPdfDimPanel.js +347 -0
  176. package/lib/ui/AcUiPdfDimPanel.js.map +1 -0
  177. package/lib/ui/AcUiPdfHatchPanel.d.ts +57 -0
  178. package/lib/ui/AcUiPdfHatchPanel.d.ts.map +1 -0
  179. package/lib/ui/AcUiPdfHatchPanel.js +420 -0
  180. package/lib/ui/AcUiPdfHatchPanel.js.map +1 -0
  181. package/lib/ui/AcUiPdfImportDialog.d.ts +120 -0
  182. package/lib/ui/AcUiPdfImportDialog.d.ts.map +1 -0
  183. package/lib/ui/AcUiPdfImportDialog.js +673 -0
  184. package/lib/ui/AcUiPdfImportDialog.js.map +1 -0
  185. package/lib/ui/AcUiPdfTextPanel.d.ts +95 -0
  186. package/lib/ui/AcUiPdfTextPanel.d.ts.map +1 -0
  187. package/lib/ui/AcUiPdfTextPanel.js +775 -0
  188. package/lib/ui/AcUiPdfTextPanel.js.map +1 -0
  189. package/package.json +11 -11
@@ -1,3 +1,14 @@
1
+ var __assign = (this && this.__assign) || function () {
2
+ __assign = Object.assign || function(t) {
3
+ for (var s, i = 1, n = arguments.length; i < n; i++) {
4
+ s = arguments[i];
5
+ for (var p in s) if (Object.prototype.hasOwnProperty.call(s, p))
6
+ t[p] = s[p];
7
+ }
8
+ return t;
9
+ };
10
+ return __assign.apply(this, arguments);
11
+ };
1
12
  var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) {
2
13
  function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); }
3
14
  return new (P || (P = Promise))(function (resolve, reject) {
@@ -34,6 +45,17 @@ var __generator = (this && this.__generator) || function (thisArg, body) {
34
45
  if (op[0] & 5) throw op[1]; return { value: op[0] ? op[1] : void 0, done: true };
35
46
  }
36
47
  };
48
+ var __rest = (this && this.__rest) || function (s, e) {
49
+ var t = {};
50
+ for (var p in s) if (Object.prototype.hasOwnProperty.call(s, p) && e.indexOf(p) < 0)
51
+ t[p] = s[p];
52
+ if (s != null && typeof Object.getOwnPropertySymbols === "function")
53
+ for (var i = 0, p = Object.getOwnPropertySymbols(s); i < p.length; i++) {
54
+ if (e.indexOf(p[i]) < 0 && Object.prototype.propertyIsEnumerable.call(s, p[i]))
55
+ t[p[i]] = s[p[i]];
56
+ }
57
+ return t;
58
+ };
37
59
  var __read = (this && this.__read) || function (o, n) {
38
60
  var m = typeof Symbol === "function" && o[Symbol.iterator];
39
61
  if (!m) return o;
@@ -70,11 +92,22 @@ var __values = (this && this.__values) || function(o) {
70
92
  };
71
93
  throw new TypeError(s ? "Object is not iterable." : "Symbol.iterator is not defined.");
72
94
  };
73
- import { AcApDocManager, AcApI18n, AcEdCorsorType } from '@mlightcad/cad-simple-viewer';
74
- import { AcCmColor, AcDbLine, AcDbPolyline, AcDbText, AcGePoint2d, AcGePoint3d, log } from '@mlightcad/data-model';
95
+ import { AcApDocManager, AcApFontUtil, AcApI18n, AcEdCorsorType, AcEdPromptDoubleOptions, AcEdPromptIntegerOptions, AcEdPromptKeywordOptions, AcEdPromptPointOptions, AcEdPromptStatus } from '@mlightcad/cad-simple-viewer';
96
+ import { AcCmColor, AcDbArc, AcDbBlockReference, AcDbBlockTableRecord, AcDbCircle, AcDbEllipse, AcDbLine, AcDbPolyline, AcDbRasterImage, AcDbRasterImageDef, AcDbSpline, AcDbText, AcGePoint2d, AcGePoint3d, AcGeVector3d, log } from '@mlightcad/data-model';
75
97
  import * as pdfjsLib from 'pdfjs-dist';
98
+ import { acapPdfT } from './acapPdfI18n';
99
+ import { resolveAcApPdfImportOptions } from './AcApPdfImportOptions';
100
+ import { acapPdfImportResourceUrls } from './AcApPdfImportResources';
101
+ import { acapPdfAppendEntities } from './pdfImportAppend';
102
+ import { acapPdfCreatePatternHatch, acapPdfCreateSolidHatch, acapPdfEnsureDashLinetype, acapPdfEnsureTextStyle, acapPdfFitWidthFactor, acapPdfFontFamily, acapPdfShapeToLoop } from './pdfImportEntities';
103
+ import { acapPdfRasterizeImage } from './pdfImportImages';
104
+ import { buildPdfImportShapes, orderPdfImportPaints } from './pdfImportShapes';
76
105
  import { allocatePdfFallbackLayerName, collectPdfOcgLayers, normalizeCadLayerKey, pdfOperatorListHasOptionalContent } from './pdfOptionalContent';
77
- import { extractPdfImportSubpaths } from './pdfVectorImport';
106
+ import { extractPdfImportSubpaths, PDF_IMPORT_FOREGROUND_COLOR } from './pdfVectorImport';
107
+ import { buildPdfFormBlocks } from './recognition/pdfFormBlocks';
108
+ import { acapPdfRecognizeHatches } from './recognition/pdfHatchRecognition';
109
+ import { mergePdfTextRuns } from './recognition/pdfTextRunMerge';
110
+ import { AcUiPdfImportDialog } from './ui/AcUiPdfImportDialog';
78
111
  /**
79
112
  * PDF.js worker shipped beside this module.
80
113
  *
@@ -86,6 +119,61 @@ import { extractPdfImportSubpaths } from './pdfVectorImport';
86
119
  */
87
120
  var PDF_WORKER_URL = new URL('../node_modules/pdfjs-dist/build/pdf.worker.mjs', import.meta.url);
88
121
  pdfjsLib.GlobalWorkerOptions.workerSrc = PDF_WORKER_URL.href;
122
+ /**
123
+ * `getDocument` parameters. CMaps and standard fonts are required for CID
124
+ * (e.g. Chinese) fonts; without them PDF.js returns empty glyph runs.
125
+ */
126
+ function pdfDocumentParams(data) {
127
+ return __assign(__assign({ data: data }, acapPdfImportResourceUrls(pdfjsLib.version)), { cMapPacked: true });
128
+ }
129
+ /** Mode last picked at the `-pdfimport` prompt; reused as the next default. */
130
+ var lastImportMode = 'recover';
131
+ /** i18n key of the prompt label for `mode`. */
132
+ function importModeLabelKey(mode) {
133
+ return mode === 'visual'
134
+ ? 'jig.pdfimport.modeVisual'
135
+ : 'jig.pdfimport.modeRecover';
136
+ }
137
+ /** Adds the `jig.pdfimport.keywords.<name>` keyword to `keywords`. */
138
+ function addPdfImportKeyword(keywords, name) {
139
+ var base = "jig.pdfimport.keywords.".concat(name);
140
+ return keywords.add(AcApI18n.t("".concat(base, ".display")), AcApI18n.t("".concat(base, ".global")), AcApI18n.t("".concat(base, ".local")));
141
+ }
142
+ /**
143
+ * Values last confirmed in the Import PDF dialog; the next `pdfimport` starts
144
+ * from them (page number excepted, as the next file differs).
145
+ */
146
+ var lastDialogValues = {};
147
+ /** Adapts a pdf.js document to what {@link AcUiPdfImportDialog} draws. */
148
+ function pdfDialogDocument(pdf) {
149
+ var _this = this;
150
+ return {
151
+ numPages: pdf.numPages,
152
+ getPage: function (pageNumber) { return __awaiter(_this, void 0, void 0, function () {
153
+ var page;
154
+ return __generator(this, function (_a) {
155
+ switch (_a.label) {
156
+ case 0: return [4 /*yield*/, pdf.getPage(pageNumber)];
157
+ case 1:
158
+ page = _a.sent();
159
+ return [2 /*return*/, {
160
+ getSize: function (scale) {
161
+ var viewport = page.getViewport({ scale: scale });
162
+ return { width: viewport.width, height: viewport.height };
163
+ },
164
+ render: function (canvas, scale) {
165
+ var task = page.render({
166
+ canvas: canvas,
167
+ viewport: page.getViewport({ scale: scale })
168
+ });
169
+ return { promise: task.promise, cancel: function () { return task.cancel(); } };
170
+ }
171
+ }];
172
+ }
173
+ });
174
+ }); }
175
+ };
176
+ }
89
177
  /**
90
178
  * Converts a PDF file into CAD entities appended to the current document's
91
179
  * model space.
@@ -94,7 +182,128 @@ var AcApPdfImportConvertor = /** @class */ (function () {
94
182
  function AcApPdfImportConvertor() {
95
183
  }
96
184
  /**
97
- * Prompts the user to pick a PDF file and imports vector geometry.
185
+ * Prompts the user to pick a PDF file, shows the Import PDF dialog (page,
186
+ * insertion point, scale, import mode) and imports vector geometry
187
+ * (`pdfimport`).
188
+ *
189
+ * Returns without database edits when the picker or the dialog is
190
+ * dismissed. The command undo mark then has no committed changes, so
191
+ * nothing is pushed onto the undo stack.
192
+ *
193
+ * @param context - Application context for the target document
194
+ */
195
+ AcApPdfImportConvertor.prototype.importFromFilePicker = function (context) {
196
+ return __awaiter(this, void 0, void 0, function () {
197
+ var loaded, load, first, pdfBySource_1, result, source, values, pdf, insertionPoint, picked;
198
+ var _this = this;
199
+ var _a, _b;
200
+ return __generator(this, function (_c) {
201
+ switch (_c.label) {
202
+ case 0:
203
+ loaded = new Set();
204
+ load = function () { return __awaiter(_this, void 0, void 0, function () {
205
+ var file, buffer, pdf;
206
+ return __generator(this, function (_a) {
207
+ switch (_a.label) {
208
+ case 0: return [4 /*yield*/, this.pickPdfFile()];
209
+ case 1:
210
+ file = _a.sent();
211
+ if (!file)
212
+ return [2 /*return*/, undefined];
213
+ return [4 /*yield*/, file.arrayBuffer()];
214
+ case 2:
215
+ buffer = _a.sent();
216
+ return [4 /*yield*/, pdfjsLib.getDocument(pdfDocumentParams(buffer)).promise];
217
+ case 3:
218
+ pdf = _a.sent();
219
+ loaded.add(pdf);
220
+ return [2 /*return*/, { pdf: pdf, document: pdfDialogDocument(pdf), fileName: file.name }];
221
+ }
222
+ });
223
+ }); };
224
+ _c.label = 1;
225
+ case 1:
226
+ _c.trys.push([1, , 7, 9]);
227
+ return [4 /*yield*/, load()
228
+ // Chrome drops an SVG data-URI cursor after the native file dialog.
229
+ ];
230
+ case 2:
231
+ first = _c.sent();
232
+ // Chrome drops an SVG data-URI cursor after the native file dialog.
233
+ restoreViewCursor(context);
234
+ if (!first)
235
+ return [2 /*return*/];
236
+ pdfBySource_1 = new Map();
237
+ pdfBySource_1.set(first, first.pdf);
238
+ return [4 /*yield*/, AcUiPdfImportDialog.open({
239
+ host: (_b = (_a = context.view) === null || _a === void 0 ? void 0 : _a.container) !== null && _b !== void 0 ? _b : document.body,
240
+ source: first,
241
+ initial: lastDialogValues,
242
+ browse: function () { return __awaiter(_this, void 0, void 0, function () {
243
+ var next, error_1;
244
+ return __generator(this, function (_a) {
245
+ switch (_a.label) {
246
+ case 0:
247
+ _a.trys.push([0, 2, 3, 4]);
248
+ return [4 /*yield*/, load()];
249
+ case 1:
250
+ next = _a.sent();
251
+ if (next)
252
+ pdfBySource_1.set(next, next.pdf);
253
+ return [2 /*return*/, next];
254
+ case 2:
255
+ error_1 = _a.sent();
256
+ log.warn('[pdfimport] Failed to open PDF:', error_1);
257
+ return [2 /*return*/, undefined];
258
+ case 3:
259
+ restoreViewCursor(context);
260
+ return [7 /*endfinally*/];
261
+ case 4: return [2 /*return*/];
262
+ }
263
+ });
264
+ }); }
265
+ })];
266
+ case 3:
267
+ result = _c.sent();
268
+ if (!result)
269
+ return [2 /*return*/];
270
+ source = result.source, values = __rest(result, ["source"]);
271
+ lastDialogValues = __assign(__assign({}, values), { pageNumber: undefined });
272
+ pdf = pdfBySource_1.get(source);
273
+ if (!pdf)
274
+ return [2 /*return*/];
275
+ insertionPoint = values.insertionPoint;
276
+ if (!values.specifyOnScreen) return [3 /*break*/, 5];
277
+ return [4 /*yield*/, this.promptInsertionPoint()];
278
+ case 4:
279
+ picked = _c.sent();
280
+ if (!picked)
281
+ return [2 /*return*/];
282
+ insertionPoint = picked;
283
+ _c.label = 5;
284
+ case 5: return [4 /*yield*/, this.importDocument(context, pdf, resolveAcApPdfImportOptions({
285
+ mode: values.mode,
286
+ pageNumber: values.pageNumber,
287
+ scale: values.scale,
288
+ insertionPoint: insertionPoint
289
+ }))];
290
+ case 6:
291
+ _c.sent();
292
+ return [3 /*break*/, 9];
293
+ case 7: return [4 /*yield*/, Promise.all(__spreadArray([], __read(loaded), false).map(function (pdf) { return pdf.destroy(); }))];
294
+ case 8:
295
+ _c.sent();
296
+ restoreViewCursor(context);
297
+ return [7 /*endfinally*/];
298
+ case 9: return [2 /*return*/];
299
+ }
300
+ });
301
+ });
302
+ };
303
+ /**
304
+ * Prompts the user to pick a PDF file, asks for page / insertion point /
305
+ * scale / mode on the command line, and imports vector geometry
306
+ * (`-pdfimport`).
98
307
  *
99
308
  * Returns without database edits when the picker is dismissed. The command
100
309
  * undo mark then has no committed changes, so nothing is pushed onto the
@@ -102,13 +311,13 @@ var AcApPdfImportConvertor = /** @class */ (function () {
102
311
  *
103
312
  * @param context - Application context for the target document
104
313
  */
105
- AcApPdfImportConvertor.prototype.importFromFilePicker = function (context) {
314
+ AcApPdfImportConvertor.prototype.importFromCommandLine = function (context) {
106
315
  return __awaiter(this, void 0, void 0, function () {
107
- var file, buffer;
316
+ var file, buffer, pdf, prompted;
108
317
  return __generator(this, function (_a) {
109
318
  switch (_a.label) {
110
319
  case 0:
111
- _a.trys.push([0, , 4, 5]);
320
+ _a.trys.push([0, , 10, 11]);
112
321
  return [4 /*yield*/, this.pickPdfFile()];
113
322
  case 1:
114
323
  file = _a.sent();
@@ -117,15 +326,31 @@ var AcApPdfImportConvertor = /** @class */ (function () {
117
326
  return [4 /*yield*/, file.arrayBuffer()];
118
327
  case 2:
119
328
  buffer = _a.sent();
120
- return [4 /*yield*/, this.convert(context, buffer)];
329
+ return [4 /*yield*/, pdfjsLib.getDocument(pdfDocumentParams(buffer)).promise];
121
330
  case 3:
122
- _a.sent();
123
- return [3 /*break*/, 5];
331
+ pdf = _a.sent();
332
+ _a.label = 4;
124
333
  case 4:
334
+ _a.trys.push([4, , 7, 9]);
335
+ return [4 /*yield*/, this.promptImportOptions(pdf.numPages)];
336
+ case 5:
337
+ prompted = _a.sent();
338
+ if (!prompted)
339
+ return [2 /*return*/];
340
+ return [4 /*yield*/, this.importDocument(context, pdf, resolveAcApPdfImportOptions(prompted))];
341
+ case 6:
342
+ _a.sent();
343
+ return [3 /*break*/, 9];
344
+ case 7: return [4 /*yield*/, pdf.destroy()];
345
+ case 8:
346
+ _a.sent();
347
+ return [7 /*endfinally*/];
348
+ case 9: return [3 /*break*/, 11];
349
+ case 10:
125
350
  // Chrome drops an SVG data-URI cursor after the native file dialog.
126
351
  restoreViewCursor(context);
127
352
  return [7 /*endfinally*/];
128
- case 5: return [2 /*return*/];
353
+ case 11: return [2 /*return*/];
129
354
  }
130
355
  });
131
356
  });
@@ -135,7 +360,7 @@ var AcApPdfImportConvertor = /** @class */ (function () {
135
360
  *
136
361
  * Resolves `undefined` when the user cancels the picker. `cancel` does not
137
362
  * fire for every dismiss path, so closing the dialog (window focus with no
138
- * selected file) also settles the promise. Otherwise `ipdf` would stay
363
+ * selected file) also settles the promise. Otherwise `pdfimport` would stay
139
364
  * inside its write transaction.
140
365
  */
141
366
  AcApPdfImportConvertor.prototype.pickPdfFile = function () {
@@ -180,13 +405,48 @@ var AcApPdfImportConvertor = /** @class */ (function () {
180
405
  }, 0);
181
406
  });
182
407
  };
408
+ /**
409
+ * Imports one PDF page into model space.
410
+ *
411
+ * @param context - Application context for the target document
412
+ * @param data - PDF file bytes
413
+ * @param pageNumberOrOptions - 1-based page number, or full import options
414
+ */
183
415
  AcApPdfImportConvertor.prototype.convert = function (context_1, data_1) {
184
- return __awaiter(this, arguments, void 0, function (context, data, pageNumber) {
416
+ return __awaiter(this, arguments, void 0, function (context, data, pageNumberOrOptions) {
417
+ var options, pdf;
418
+ if (pageNumberOrOptions === void 0) { pageNumberOrOptions = 1; }
419
+ return __generator(this, function (_a) {
420
+ switch (_a.label) {
421
+ case 0:
422
+ options = resolveAcApPdfImportOptions(typeof pageNumberOrOptions === 'number'
423
+ ? { pageNumber: pageNumberOrOptions }
424
+ : pageNumberOrOptions);
425
+ return [4 /*yield*/, pdfjsLib.getDocument(pdfDocumentParams(data)).promise];
426
+ case 1:
427
+ pdf = _a.sent();
428
+ _a.label = 2;
429
+ case 2:
430
+ _a.trys.push([2, , 4, 6]);
431
+ return [4 /*yield*/, this.importDocument(context, pdf, options)];
432
+ case 3:
433
+ _a.sent();
434
+ return [3 /*break*/, 6];
435
+ case 4: return [4 /*yield*/, pdf.destroy()];
436
+ case 5:
437
+ _a.sent();
438
+ return [7 /*endfinally*/];
439
+ case 6: return [2 /*return*/];
440
+ }
441
+ });
442
+ });
443
+ };
444
+ AcApPdfImportConvertor.prototype.importDocument = function (context, pdf, options) {
445
+ return __awaiter(this, void 0, void 0, function () {
185
446
  var _this = this;
186
- if (pageNumber === void 0) { pageNumber = 1; }
187
447
  return __generator(this, function (_a) {
188
448
  switch (_a.label) {
189
- case 0: return [4 /*yield*/, AcApDocManager.instance.withBusyIndicator(function () { return _this.importPage(context, data, pageNumber); }, AcApI18n.t('main.message.importingPdf'))];
449
+ case 0: return [4 /*yield*/, AcApDocManager.instance.withBusyIndicator(function () { return _this.importPage(context, pdf, options); }, AcApI18n.t('main.message.importingPdf'))];
190
450
  case 1:
191
451
  _a.sent();
192
452
  return [2 /*return*/];
@@ -194,86 +454,438 @@ var AcApPdfImportConvertor = /** @class */ (function () {
194
454
  });
195
455
  });
196
456
  };
197
- AcApPdfImportConvertor.prototype.importPage = function (context, data, pageNumber) {
457
+ /**
458
+ * Command-line prompts: page (multi-page files only), then insertion point
459
+ * with `Scale` and `Mode` (recover the drawing / keep the PDF look)
460
+ * options.
461
+ *
462
+ * @returns Options to import with, or `undefined` when the user cancels.
463
+ */
464
+ AcApPdfImportConvertor.prototype.promptImportOptions = function (pageCount) {
198
465
  return __awaiter(this, void 0, void 0, function () {
199
- var pdf, page, viewport, operatorList, optionalContentConfig, reservedLayerNames, ocgLayers, fallbackLayerName, _a, subpaths, texts, entities, usedLayerNames, subpaths_1, subpaths_1_1, subpath, entity, texts_1, texts_1_1, textRun, entity, layerService, existed, existedKeys, _b, _c, layerInfo, modelSpace, entities_1, entities_1_1, entity, err_1;
200
- var e_1, _d, e_2, _e, e_3, _f, e_4, _g;
201
- return __generator(this, function (_h) {
202
- switch (_h.label) {
466
+ var editor, options, pagePrompt, pageResult, scale, mode, pointPrompt, result, picked, scalePrompt, scaleResult;
467
+ var _a, _b;
468
+ return __generator(this, function (_c) {
469
+ switch (_c.label) {
203
470
  case 0:
204
- _h.trys.push([0, 5, , 6]);
205
- return [4 /*yield*/, pdfjsLib.getDocument({ data: data }).promise];
471
+ editor = AcApDocManager.instance.editor;
472
+ options = {};
473
+ if (!(pageCount > 1)) return [3 /*break*/, 2];
474
+ pagePrompt = new AcEdPromptIntegerOptions(acapPdfT('jig.pdfimport.pageNumber', { count: pageCount }), 1, pageCount);
475
+ pagePrompt.defaultValue = 1;
476
+ pagePrompt.useDefaultValue = true;
477
+ pagePrompt.allowNone = true;
478
+ return [4 /*yield*/, editor.getInteger(pagePrompt)];
206
479
  case 1:
207
- pdf = _h.sent();
208
- return [4 /*yield*/, pdf.getPage(pageNumber)];
480
+ pageResult = _c.sent();
481
+ if (pageResult.status === AcEdPromptStatus.OK) {
482
+ options.pageNumber = (_a = pageResult.value) !== null && _a !== void 0 ? _a : 1;
483
+ }
484
+ else if (pageResult.status !== AcEdPromptStatus.None) {
485
+ return [2 /*return*/, undefined];
486
+ }
487
+ _c.label = 2;
209
488
  case 2:
210
- page = _h.sent();
211
- viewport = page.getViewport({ scale: 1 });
212
- return [4 /*yield*/, page.getOperatorList()];
489
+ scale = 1;
490
+ mode = lastImportMode;
491
+ _c.label = 3;
213
492
  case 3:
214
- operatorList = _h.sent();
493
+ if (!true) return [3 /*break*/, 9];
494
+ pointPrompt = new AcEdPromptPointOptions(acapPdfT('jig.pdfimport.insertionPoint', {
495
+ scale: String(scale),
496
+ mode: AcApI18n.t(importModeLabelKey(mode))
497
+ }));
498
+ pointPrompt.allowNone = true;
499
+ addPdfImportKeyword(pointPrompt.keywords, 'scale');
500
+ addPdfImportKeyword(pointPrompt.keywords, 'mode');
501
+ return [4 /*yield*/, editor.getPoint(pointPrompt)];
502
+ case 4:
503
+ result = _c.sent();
504
+ if (result.status === AcEdPromptStatus.OK && result.value) {
505
+ options.insertionPoint = { x: result.value.x, y: result.value.y };
506
+ return [3 /*break*/, 9];
507
+ }
508
+ if (result.status === AcEdPromptStatus.None)
509
+ return [3 /*break*/, 9];
510
+ if (result.status !== AcEdPromptStatus.Keyword)
511
+ return [2 /*return*/, undefined];
512
+ if (!(result.stringResult === 'Mode')) return [3 /*break*/, 6];
513
+ return [4 /*yield*/, this.promptImportMode(mode)];
514
+ case 5:
515
+ picked = _c.sent();
516
+ if (!picked)
517
+ return [2 /*return*/, undefined];
518
+ mode = picked;
519
+ return [3 /*break*/, 3];
520
+ case 6:
521
+ if (!(result.stringResult === 'Scale')) return [3 /*break*/, 8];
522
+ scalePrompt = new AcEdPromptDoubleOptions(AcApI18n.t('jig.pdfimport.scaleFactor'));
523
+ scalePrompt.defaultValue = scale;
524
+ scalePrompt.useDefaultValue = true;
525
+ scalePrompt.allowNone = true;
526
+ scalePrompt.allowNegative = false;
527
+ scalePrompt.allowZero = false;
528
+ return [4 /*yield*/, editor.getDouble(scalePrompt)];
529
+ case 7:
530
+ scaleResult = _c.sent();
531
+ if (scaleResult.status === AcEdPromptStatus.OK) {
532
+ scale = (_b = scaleResult.value) !== null && _b !== void 0 ? _b : scale;
533
+ }
534
+ else if (scaleResult.status !== AcEdPromptStatus.None) {
535
+ return [2 /*return*/, undefined];
536
+ }
537
+ _c.label = 8;
538
+ case 8: return [3 /*break*/, 3];
539
+ case 9:
540
+ options.scale = scale;
541
+ options.mode = mode;
542
+ lastImportMode = mode;
543
+ return [2 /*return*/, options];
544
+ }
545
+ });
546
+ });
547
+ };
548
+ /**
549
+ * Asks for the import mode; Enter keeps `current`.
550
+ *
551
+ * @returns The chosen mode, or `undefined` when the user cancels.
552
+ */
553
+ AcApPdfImportConvertor.prototype.promptImportMode = function (current) {
554
+ return __awaiter(this, void 0, void 0, function () {
555
+ var prompt, recover, visual, result;
556
+ return __generator(this, function (_a) {
557
+ switch (_a.label) {
558
+ case 0:
559
+ prompt = new AcEdPromptKeywordOptions(AcApI18n.t('jig.pdfimport.modePrompt'));
560
+ prompt.allowNone = true;
561
+ recover = addPdfImportKeyword(prompt.keywords, 'recover');
562
+ visual = addPdfImportKeyword(prompt.keywords, 'visual');
563
+ prompt.keywords.default = current === 'visual' ? visual : recover;
564
+ return [4 /*yield*/, AcApDocManager.instance.editor.getKeywords(prompt)];
565
+ case 1:
566
+ result = _a.sent();
567
+ if (result.status === AcEdPromptStatus.None)
568
+ return [2 /*return*/, current];
569
+ if (result.status !== AcEdPromptStatus.OK &&
570
+ result.status !== AcEdPromptStatus.Keyword) {
571
+ return [2 /*return*/, undefined];
572
+ }
573
+ if (result.stringResult === 'Visual')
574
+ return [2 /*return*/, 'visual'];
575
+ if (result.stringResult === 'Recover')
576
+ return [2 /*return*/, 'recover'];
577
+ return [2 /*return*/, current];
578
+ }
579
+ });
580
+ });
581
+ };
582
+ /**
583
+ * Asks for the insertion point in the drawing. Enter takes the origin.
584
+ *
585
+ * @returns The point, or `undefined` when the user cancels.
586
+ */
587
+ AcApPdfImportConvertor.prototype.promptInsertionPoint = function () {
588
+ return __awaiter(this, void 0, void 0, function () {
589
+ var prompt, result;
590
+ return __generator(this, function (_a) {
591
+ switch (_a.label) {
592
+ case 0:
593
+ prompt = new AcEdPromptPointOptions(AcApI18n.t('jig.pdfimport.pickInsertionPoint'));
594
+ prompt.allowNone = true;
595
+ return [4 /*yield*/, AcApDocManager.instance.editor.getPoint(prompt)];
596
+ case 1:
597
+ result = _a.sent();
598
+ if (result.status === AcEdPromptStatus.OK && result.value) {
599
+ return [2 /*return*/, { x: result.value.x, y: result.value.y }];
600
+ }
601
+ if (result.status === AcEdPromptStatus.None)
602
+ return [2 /*return*/, { x: 0, y: 0 }];
603
+ return [2 /*return*/, undefined];
604
+ }
605
+ });
606
+ });
607
+ };
608
+ AcApPdfImportConvertor.prototype.importPage = function (context, pdf, options) {
609
+ return __awaiter(this, void 0, void 0, function () {
610
+ var page_1, viewport, operatorList, optionalContentConfig, reservedLayerNames, ocgLayers, fallbackLayerName, content, formBlocks_1, _a, items, stats, recognized, itemIndex_1, hatchAt, _b, _c, hatch, db_1, usedLayerNames_1, createEntity, entities, hatchCount, patternHatchCount, _d, _e, paint, index, found, hatch_1, entity, group, loops, hatch, group_1, group_1_1, item, entity, first, blockTable, referenceCount, _f, _g, block, blockEntities, name_1, record, insertionPoint, scale, _h, _j, placement, ref, texts, styleByFont_1, styleFor, textEntities, texts_1, texts_1_1, textRun, entity, style, imageEntities, _k, imageEntities_1, imageEntities_1_1, image, ordered, layerService, existed, existedKeys, _l, _m, layerInfo, err_1;
611
+ var e_1, _o, e_2, _p, e_3, _q, e_4, _r, e_5, _s, e_6, _t, e_7, _u, e_8, _v;
612
+ var _w, _x;
613
+ return __generator(this, function (_y) {
614
+ switch (_y.label) {
615
+ case 0:
616
+ _y.trys.push([0, 9, , 10]);
617
+ return [4 /*yield*/, pdf.getPage(options.pageNumber)];
618
+ case 1:
619
+ page_1 = _y.sent();
620
+ viewport = page_1.getViewport({ scale: 1 });
621
+ return [4 /*yield*/, page_1.getOperatorList()];
622
+ case 2:
623
+ operatorList = _y.sent();
215
624
  return [4 /*yield*/, pdf.getOptionalContentConfig({
216
625
  intent: 'display'
217
626
  })];
218
- case 4:
219
- optionalContentConfig = (_h.sent());
627
+ case 3:
628
+ optionalContentConfig = (_y.sent());
220
629
  reservedLayerNames = databaseLayerNames(context);
221
630
  ocgLayers = collectPdfOcgLayers(operatorList, pdfjsLib.OPS.beginMarkedContentProps, optionalContentConfig, reservedLayerNames);
222
631
  fallbackLayerName = pdfOperatorListHasOptionalContent(operatorList, pdfjsLib.OPS.beginMarkedContentProps)
223
632
  ? allocatePdfFallbackLayerName(reservedLayerNames, __spreadArray([], __read(ocgLayers.values()), false).map(function (layer) { return layer.layerName; }))
224
633
  : undefined;
225
- _a = extractPdfImportSubpaths(operatorList, pdfjsLib.OPS, viewport, ocgLayers, fallbackLayerName), subpaths = _a.subpaths, texts = _a.texts;
226
- entities = [];
227
- usedLayerNames = new Set();
634
+ content = extractPdfImportSubpaths(operatorList, pdfjsLib.OPS, viewport, ocgLayers, fallbackLayerName, { remapContrastInk: true, paperTone: 'auto' });
635
+ formBlocks_1 = options.formBlocks
636
+ ? buildPdfFormBlocks(content, {
637
+ curveRecognition: options.curveRecognition
638
+ })
639
+ : { blocks: [], consumed: new Set() };
640
+ _a = buildPdfImportShapes({
641
+ subpaths: content.subpaths.filter(function (_, index) { return !formBlocks_1.consumed.has(index); })
642
+ }, options), items = _a.items, stats = _a.stats;
643
+ recognized = options.recognizeHatches
644
+ ? acapPdfRecognizeHatches(items, __assign({ tolerance: PDF_HATCH_TOLERANCE_MM * options.scale }, options.hatchRecognition), (_w = content.clipPaths) === null || _w === void 0 ? void 0 : _w.map(function (loops) {
645
+ return loops.map(function (loop) {
646
+ return loop.map(function (p) { return ({
647
+ x: options.insertionPoint.x + p.x * options.scale,
648
+ y: options.insertionPoint.y + p.y * options.scale
649
+ }); });
650
+ });
651
+ }))
652
+ : { hatches: [], consumed: new Set() };
653
+ itemIndex_1 = new Map();
654
+ items.forEach(function (item, index) { return itemIndex_1.set(item, index); });
655
+ hatchAt = new Map();
228
656
  try {
229
- for (subpaths_1 = __values(subpaths), subpaths_1_1 = subpaths_1.next(); !subpaths_1_1.done; subpaths_1_1 = subpaths_1.next()) {
230
- subpath = subpaths_1_1.value;
231
- if (subpath.layerName) {
232
- usedLayerNames.add(subpath.layerName);
233
- }
234
- entity = this.subpathToEntity(subpath.points, subpath.layerName, subpath.color);
235
- if (entity)
236
- entities.push(entity);
657
+ for (_b = __values(recognized.hatches), _c = _b.next(); !_c.done; _c = _b.next()) {
658
+ hatch = _c.value;
659
+ hatchAt.set(hatch.items[0], hatch);
237
660
  }
238
661
  }
239
662
  catch (e_1_1) { e_1 = { error: e_1_1 }; }
240
663
  finally {
241
664
  try {
242
- if (subpaths_1_1 && !subpaths_1_1.done && (_d = subpaths_1.return)) _d.call(subpaths_1);
665
+ if (_c && !_c.done && (_o = _b.return)) _o.call(_b);
243
666
  }
244
667
  finally { if (e_1) throw e_1.error; }
245
668
  }
669
+ db_1 = context.doc.database;
670
+ usedLayerNames_1 = new Set();
671
+ createEntity = function (item) {
672
+ var entity = shapeToEntity(item.shape);
673
+ if (!entity)
674
+ return null;
675
+ if (item.layerName) {
676
+ usedLayerNames_1.add(item.layerName);
677
+ entity.layer = item.layerName;
678
+ }
679
+ applyPdfColor(entity, item.color);
680
+ if (options.lineWeights && item.lineWidth) {
681
+ entity.lineWeight = nearestLineWeight(item.lineWidth);
682
+ }
683
+ if (options.dashLinetypes && item.dashPattern) {
684
+ entity.lineType = acapPdfEnsureDashLinetype(db_1, item.dashPattern.map(function (length) { return length * options.scale; }));
685
+ }
686
+ return entity;
687
+ };
688
+ entities = [];
689
+ hatchCount = 0;
690
+ patternHatchCount = 0;
691
+ try {
692
+ for (_d = __values(orderPdfImportPaints(items, options.fillHatches)), _e = _d.next(); !_e.done; _e = _d.next()) {
693
+ paint = _e.value;
694
+ if (paint.kind === 'shape') {
695
+ index = itemIndex_1.get(paint.item);
696
+ if (index !== undefined && recognized.consumed.has(index)) {
697
+ found = hatchAt.get(index);
698
+ hatch_1 = found && createPatternHatch(db_1, found);
699
+ if (hatch_1) {
700
+ if (found.layerName)
701
+ usedLayerNames_1.add(found.layerName);
702
+ entities.push(hatch_1);
703
+ patternHatchCount++;
704
+ }
705
+ continue;
706
+ }
707
+ entity = createEntity(paint.item);
708
+ if (entity)
709
+ entities.push(entity);
710
+ continue;
711
+ }
712
+ group = paint.items;
713
+ loops = group
714
+ .map(function (item) { return acapPdfShapeToLoop(item.shape); })
715
+ .filter(function (loop) { return !!loop; });
716
+ hatch = acapPdfCreateSolidHatch(db_1, loops);
717
+ if (!hatch) {
718
+ try {
719
+ // Nothing closed to fill: keep the outlines instead of dropping them.
720
+ for (group_1 = (e_3 = void 0, __values(group)), group_1_1 = group_1.next(); !group_1_1.done; group_1_1 = group_1.next()) {
721
+ item = group_1_1.value;
722
+ if (item.stroked)
723
+ continue;
724
+ entity = createEntity(item);
725
+ if (entity)
726
+ entities.push(entity);
727
+ }
728
+ }
729
+ catch (e_3_1) { e_3 = { error: e_3_1 }; }
730
+ finally {
731
+ try {
732
+ if (group_1_1 && !group_1_1.done && (_q = group_1.return)) _q.call(group_1);
733
+ }
734
+ finally { if (e_3) throw e_3.error; }
735
+ }
736
+ continue;
737
+ }
738
+ first = group[0];
739
+ if (first.layerName) {
740
+ usedLayerNames_1.add(first.layerName);
741
+ hatch.layer = first.layerName;
742
+ }
743
+ applyPdfColor(hatch, (_x = first.fillColor) !== null && _x !== void 0 ? _x : first.color);
744
+ entities.push(hatch);
745
+ hatchCount++;
746
+ }
747
+ }
748
+ catch (e_2_1) { e_2 = { error: e_2_1 }; }
749
+ finally {
750
+ try {
751
+ if (_e && !_e.done && (_p = _d.return)) _p.call(_d);
752
+ }
753
+ finally { if (e_2) throw e_2.error; }
754
+ }
755
+ blockTable = db_1.tables.blockTable;
756
+ referenceCount = 0;
757
+ try {
758
+ for (_f = __values(formBlocks_1.blocks), _g = _f.next(); !_g.done; _g = _f.next()) {
759
+ block = _g.value;
760
+ blockEntities = block.shapes
761
+ .map(createEntity)
762
+ .filter(function (entity) { return entity !== null; });
763
+ if (blockEntities.length === 0)
764
+ continue;
765
+ name_1 = uniqueBlockName(context, PDF_FORM_BLOCK_PREFIX);
766
+ record = new AcDbBlockTableRecord({
767
+ name: name_1,
768
+ origin: new AcGePoint3d(0, 0, 0)
769
+ });
770
+ blockTable.add(record);
771
+ record.appendEntity(blockEntities);
772
+ insertionPoint = options.insertionPoint, scale = options.scale;
773
+ try {
774
+ for (_h = (e_5 = void 0, __values(block.references)), _j = _h.next(); !_j.done; _j = _h.next()) {
775
+ placement = _j.value;
776
+ ref = new AcDbBlockReference(name_1);
777
+ ref.position = new AcGePoint3d(insertionPoint.x + placement.position.x * scale, insertionPoint.y + placement.position.y * scale, 0);
778
+ ref.rotation = placement.rotation;
779
+ ref.scaleFactors = new AcGePoint3d(placement.scaleX * scale, placement.scaleY * scale, 1);
780
+ if (placement.layerName) {
781
+ usedLayerNames_1.add(placement.layerName);
782
+ ref.layer = placement.layerName;
783
+ }
784
+ entities.push(ref);
785
+ referenceCount++;
786
+ }
787
+ }
788
+ catch (e_5_1) { e_5 = { error: e_5_1 }; }
789
+ finally {
790
+ try {
791
+ if (_j && !_j.done && (_s = _h.return)) _s.call(_h);
792
+ }
793
+ finally { if (e_5) throw e_5.error; }
794
+ }
795
+ }
796
+ }
797
+ catch (e_4_1) { e_4 = { error: e_4_1 }; }
798
+ finally {
799
+ try {
800
+ if (_g && !_g.done && (_r = _f.return)) _r.call(_f);
801
+ }
802
+ finally { if (e_4) throw e_4.error; }
803
+ }
804
+ texts = options.mergeTextRuns
805
+ ? mergePdfTextRuns(content.texts)
806
+ : content.texts;
807
+ styleByFont_1 = new Map();
808
+ styleFor = function (fontId) {
809
+ if (!options.textStyles || fontId === undefined)
810
+ return undefined;
811
+ if (!styleByFont_1.has(fontId)) {
812
+ var name_2 = pdfFontName(page_1, fontId);
813
+ styleByFont_1.set(fontId, name_2
814
+ ? acapPdfEnsureTextStyle(db_1, acapPdfFontFamily(name_2))
815
+ : undefined);
816
+ }
817
+ return styleByFont_1.get(fontId);
818
+ };
819
+ textEntities = [];
246
820
  try {
247
821
  for (texts_1 = __values(texts), texts_1_1 = texts_1.next(); !texts_1_1.done; texts_1_1 = texts_1.next()) {
248
822
  textRun = texts_1_1.value;
249
823
  if (textRun.layerName) {
250
- usedLayerNames.add(textRun.layerName);
824
+ usedLayerNames_1.add(textRun.layerName);
251
825
  }
252
- entity = this.textToEntity(textRun);
253
- if (entity)
254
- entities.push(entity);
826
+ entity = this.textToEntity(textRun, options);
827
+ if (!entity)
828
+ continue;
829
+ style = styleFor(textRun.fontId);
830
+ if (style)
831
+ entity.styleName = style;
832
+ textEntities.push({ entity: entity, run: textRun });
833
+ entities.push(entity);
255
834
  }
256
835
  }
257
- catch (e_2_1) { e_2 = { error: e_2_1 }; }
836
+ catch (e_6_1) { e_6 = { error: e_6_1 }; }
258
837
  finally {
259
838
  try {
260
- if (texts_1_1 && !texts_1_1.done && (_e = texts_1.return)) _e.call(texts_1);
839
+ if (texts_1_1 && !texts_1_1.done && (_t = texts_1.return)) _t.call(texts_1);
261
840
  }
262
- finally { if (e_2) throw e_2.error; }
841
+ finally { if (e_6) throw e_6.error; }
263
842
  }
264
- if (entities.length === 0) {
843
+ if (!options.fitTextWidth) return [3 /*break*/, 5];
844
+ return [4 /*yield*/, fitTextWidths(db_1, textEntities, options.scale)];
845
+ case 4:
846
+ _y.sent();
847
+ _y.label = 5;
848
+ case 5:
849
+ if (!(options.images && content.images)) return [3 /*break*/, 7];
850
+ return [4 /*yield*/, createImageEntities(page_1, db_1, content.images, options)];
851
+ case 6:
852
+ _k = _y.sent();
853
+ return [3 /*break*/, 8];
854
+ case 7:
855
+ _k = [];
856
+ _y.label = 8;
857
+ case 8:
858
+ imageEntities = _k;
859
+ try {
860
+ for (imageEntities_1 = __values(imageEntities), imageEntities_1_1 = imageEntities_1.next(); !imageEntities_1_1.done; imageEntities_1_1 = imageEntities_1.next()) {
861
+ image = imageEntities_1_1.value;
862
+ if (image.layer && image.layer !== '0')
863
+ usedLayerNames_1.add(image.layer);
864
+ }
865
+ }
866
+ catch (e_7_1) { e_7 = { error: e_7_1 }; }
867
+ finally {
868
+ try {
869
+ if (imageEntities_1_1 && !imageEntities_1_1.done && (_u = imageEntities_1.return)) _u.call(imageEntities_1);
870
+ }
871
+ finally { if (e_7) throw e_7.error; }
872
+ }
873
+ ordered = imageEntities.length > 0
874
+ ? imageEntities.concat(entities)
875
+ : entities;
876
+ if (ordered.length === 0) {
265
877
  log.warn('[PdfImport] No vector geometry found in PDF page.');
266
878
  return [2 /*return*/];
267
879
  }
268
880
  layerService = context.doc.layerService;
269
- existed = usedLayerNames.size > 0
270
- ? layerService.createLayers(__spreadArray([], __read(usedLayerNames), false)).existed
881
+ existed = usedLayerNames_1.size > 0
882
+ ? layerService.createLayers(__spreadArray([], __read(usedLayerNames_1), false)).existed
271
883
  : [];
272
884
  existedKeys = new Set(existed.map(normalizeCadLayerKey));
273
885
  try {
274
- for (_b = __values(ocgLayers.values()), _c = _b.next(); !_c.done; _c = _b.next()) {
275
- layerInfo = _c.value;
276
- if (!usedLayerNames.has(layerInfo.layerName))
886
+ for (_l = __values(ocgLayers.values()), _m = _l.next(); !_m.done; _m = _l.next()) {
887
+ layerInfo = _m.value;
888
+ if (!usedLayerNames_1.has(layerInfo.layerName))
277
889
  continue;
278
890
  if (existedKeys.has(normalizeCadLayerKey(layerInfo.layerName)))
279
891
  continue;
@@ -282,73 +894,38 @@ var AcApPdfImportConvertor = /** @class */ (function () {
282
894
  layerService.setLayerOn(layerInfo.layerName, false);
283
895
  }
284
896
  }
285
- catch (e_3_1) { e_3 = { error: e_3_1 }; }
286
- finally {
287
- try {
288
- if (_c && !_c.done && (_f = _b.return)) _f.call(_b);
289
- }
290
- finally { if (e_3) throw e_3.error; }
291
- }
292
- modelSpace = context.doc.database.tables.blockTable.modelSpace;
293
- try {
294
- for (entities_1 = __values(entities), entities_1_1 = entities_1.next(); !entities_1_1.done; entities_1_1 = entities_1.next()) {
295
- entity = entities_1_1.value;
296
- modelSpace.appendEntity(entity);
297
- }
298
- }
299
- catch (e_4_1) { e_4 = { error: e_4_1 }; }
897
+ catch (e_8_1) { e_8 = { error: e_8_1 }; }
300
898
  finally {
301
899
  try {
302
- if (entities_1_1 && !entities_1_1.done && (_g = entities_1.return)) _g.call(entities_1);
900
+ if (_m && !_m.done && (_v = _l.return)) _v.call(_l);
303
901
  }
304
- finally { if (e_4) throw e_4.error; }
902
+ finally { if (e_8) throw e_8.error; }
305
903
  }
306
- log.info("[PdfImport] Imported ".concat(entities.length, " entities across ").concat(usedLayerNames.size, " CAD layer(s)."));
307
- return [3 /*break*/, 6];
308
- case 5:
309
- err_1 = _h.sent();
904
+ acapPdfAppendEntities(context.doc.database.tables.blockTable.modelSpace, ordered);
905
+ log.info("[PdfImport] Imported ".concat(ordered.length, " entities across ").concat(usedLayerNames_1.size, " CAD layer(s): ") +
906
+ "".concat(stats.line, " lines, ").concat(stats.polyline, " polylines, ").concat(stats.circle, " circles, ") +
907
+ "".concat(stats.arc, " arcs, ").concat(stats.ellipse, " ellipses, ").concat(stats.spline, " splines, ") +
908
+ "mode ".concat(options.mode, ", ").concat(texts.length, " texts, ").concat(imageEntities.length, " images, ").concat(hatchCount, " hatches, ") +
909
+ "".concat(patternHatchCount, " pattern hatches (").concat(recognized.consumed.size, " strokes), ").concat(formBlocks_1.blocks.length, " blocks ") +
910
+ "(".concat(referenceCount, " references); ").concat(stats.duplicates, " duplicates skipped."));
911
+ return [3 /*break*/, 10];
912
+ case 9:
913
+ err_1 = _y.sent();
310
914
  log.error('[PdfImport] Failed to import PDF:', err_1);
311
915
  throw err_1;
312
- case 6: return [2 /*return*/];
916
+ case 10: return [2 /*return*/];
313
917
  }
314
918
  });
315
919
  });
316
920
  };
317
- AcApPdfImportConvertor.prototype.subpathToEntity = function (pts, layerName, color) {
318
- if (pts.length < 2)
319
- return null;
320
- if (pts.length === 2) {
321
- var line = new AcDbLine(new AcGePoint3d(pts[0].x, pts[0].y, 0), new AcGePoint3d(pts[1].x, pts[1].y, 0));
322
- if (layerName) {
323
- line.layer = layerName;
324
- }
325
- applyPdfColor(line, color);
326
- return line;
327
- }
328
- var poly = new AcDbPolyline();
329
- if (layerName) {
330
- poly.layer = layerName;
331
- }
332
- applyPdfColor(poly, color);
333
- for (var i = 0; i < pts.length; i++) {
334
- poly.addVertexAt(i, new AcGePoint2d(pts[i].x, pts[i].y));
335
- }
336
- var first = pts[0];
337
- var last = pts[pts.length - 1];
338
- var dx = first.x - last.x;
339
- var dy = first.y - last.y;
340
- if (Math.sqrt(dx * dx + dy * dy) < 1e-6) {
341
- poly.closed = true;
342
- }
343
- return poly;
344
- };
345
- AcApPdfImportConvertor.prototype.textToEntity = function (run) {
921
+ AcApPdfImportConvertor.prototype.textToEntity = function (run, options) {
346
922
  if (!run.text || run.height <= 0)
347
923
  return null;
924
+ var insertionPoint = options.insertionPoint, scale = options.scale;
348
925
  var text = new AcDbText();
349
926
  text.textString = run.text;
350
- text.position = new AcGePoint3d(run.position.x, run.position.y, 0);
351
- text.height = run.height;
927
+ text.position = new AcGePoint3d(insertionPoint.x + run.position.x * scale, insertionPoint.y + run.position.y * scale, 0);
928
+ text.height = run.height * scale;
352
929
  text.rotation = run.rotation;
353
930
  if (Number.isFinite(run.widthFactor) && run.widthFactor > 0) {
354
931
  text.widthFactor = run.widthFactor;
@@ -362,9 +939,323 @@ var AcApPdfImportConvertor = /** @class */ (function () {
362
939
  return AcApPdfImportConvertor;
363
940
  }());
364
941
  export { AcApPdfImportConvertor };
942
+ /** File name prefix of image definitions created for PDF images. */
943
+ var PDF_IMAGE_PREFIX = 'PDF_IMAGE_';
944
+ /** How long to wait for PDF.js to deliver one decoded image. */
945
+ var PDF_IMAGE_TIMEOUT_MS = 10000;
946
+ /**
947
+ * Turns PDF image paints into raster images. Each image is redrawn upright
948
+ * with its rotation / mirroring baked in; the PNG is kept in memory on the
949
+ * entity (`AcDbRasterImage.image`) and its definition is named
950
+ * `PDF_IMAGE_<n>.png`.
951
+ */
952
+ function createImageEntities(page, db, images, options) {
953
+ return __awaiter(this, void 0, void 0, function () {
954
+ var scale, insertionPoint, decoded, result, images_1, images_1_1, paint, image, pending_1, _a, a, b, c, d, e, f, raster, err_2, fileName, imageDef, entity, e_9_1;
955
+ var e_9, _b;
956
+ return __generator(this, function (_c) {
957
+ switch (_c.label) {
958
+ case 0:
959
+ scale = options.scale, insertionPoint = options.insertionPoint;
960
+ decoded = new Map();
961
+ result = [];
962
+ _c.label = 1;
963
+ case 1:
964
+ _c.trys.push([1, 12, 13, 14]);
965
+ images_1 = __values(images), images_1_1 = images_1.next();
966
+ _c.label = 2;
967
+ case 2:
968
+ if (!!images_1_1.done) return [3 /*break*/, 11];
969
+ paint = images_1_1.value;
970
+ image = void 0;
971
+ if (!paint.objId) return [3 /*break*/, 4];
972
+ pending_1 = decoded.get(paint.objId);
973
+ if (!pending_1) {
974
+ pending_1 = pdfImageObject(page, paint.objId);
975
+ decoded.set(paint.objId, pending_1);
976
+ }
977
+ return [4 /*yield*/, pending_1];
978
+ case 3:
979
+ image = _c.sent();
980
+ return [3 /*break*/, 5];
981
+ case 4:
982
+ image = paint.inline;
983
+ _c.label = 5;
984
+ case 5:
985
+ if (!image)
986
+ return [3 /*break*/, 10];
987
+ _a = paint.toCad, a = _a.a, b = _a.b, c = _a.c, d = _a.d, e = _a.e, f = _a.f;
988
+ raster = void 0;
989
+ _c.label = 6;
990
+ case 6:
991
+ _c.trys.push([6, 8, , 9]);
992
+ return [4 /*yield*/, acapPdfRasterizeImage(image, {
993
+ a: a * scale,
994
+ b: b * scale,
995
+ c: c * scale,
996
+ d: d * scale,
997
+ e: insertionPoint.x + e * scale,
998
+ f: insertionPoint.y + f * scale
999
+ })];
1000
+ case 7:
1001
+ raster = _c.sent();
1002
+ return [3 /*break*/, 9];
1003
+ case 8:
1004
+ err_2 = _c.sent();
1005
+ log.warn('[PdfImport] Skipped an image that could not be drawn:', err_2);
1006
+ return [3 /*break*/, 10];
1007
+ case 9:
1008
+ if (!raster)
1009
+ return [3 /*break*/, 10];
1010
+ fileName = uniqueImageFileName(db);
1011
+ imageDef = new AcDbRasterImageDef();
1012
+ imageDef.sourceFileName = fileName;
1013
+ imageDef.imageSize = new AcGePoint2d(raster.pixelWidth, raster.pixelHeight);
1014
+ imageDef.isLoaded = true;
1015
+ db.objects.imageDefinition.setAt(fileName, imageDef);
1016
+ entity = new AcDbRasterImage();
1017
+ entity.position = new AcGePoint3d(raster.box.x, raster.box.y, 0);
1018
+ entity.width = raster.box.width;
1019
+ entity.height = raster.box.height;
1020
+ entity.imageSize = new AcGePoint2d(raster.pixelWidth, raster.pixelHeight);
1021
+ entity.image = raster.png;
1022
+ entity.imageDefId = imageDef.objectId;
1023
+ if (paint.layerName)
1024
+ entity.layer = paint.layerName;
1025
+ result.push(entity);
1026
+ _c.label = 10;
1027
+ case 10:
1028
+ images_1_1 = images_1.next();
1029
+ return [3 /*break*/, 2];
1030
+ case 11: return [3 /*break*/, 14];
1031
+ case 12:
1032
+ e_9_1 = _c.sent();
1033
+ e_9 = { error: e_9_1 };
1034
+ return [3 /*break*/, 14];
1035
+ case 13:
1036
+ try {
1037
+ if (images_1_1 && !images_1_1.done && (_b = images_1.return)) _b.call(images_1);
1038
+ }
1039
+ finally { if (e_9) throw e_9.error; }
1040
+ return [7 /*endfinally*/];
1041
+ case 14: return [2 /*return*/, result];
1042
+ }
1043
+ });
1044
+ });
1045
+ }
1046
+ /** Waits for PDF.js to deliver a decoded image object. */
1047
+ function pdfImageObject(page, objId) {
1048
+ var store = objId.startsWith('g_') ? page.commonObjs : page.objs;
1049
+ return new Promise(function (resolve) {
1050
+ var timer = setTimeout(function () {
1051
+ log.warn("[PdfImport] Timed out waiting for image ".concat(objId, "."));
1052
+ resolve(undefined);
1053
+ }, PDF_IMAGE_TIMEOUT_MS);
1054
+ try {
1055
+ store.get(objId, function (data) {
1056
+ clearTimeout(timer);
1057
+ resolve((data !== null && data !== void 0 ? data : undefined));
1058
+ });
1059
+ }
1060
+ catch (err) {
1061
+ clearTimeout(timer);
1062
+ log.warn("[PdfImport] Image ".concat(objId, " is not available:"), err);
1063
+ resolve(undefined);
1064
+ }
1065
+ });
1066
+ }
1067
+ /** First `PDF_IMAGE_<n>.png` not used by an image definition. */
1068
+ function uniqueImageFileName(db) {
1069
+ var index = 1;
1070
+ while (db.objects.imageDefinition.has("".concat(PDF_IMAGE_PREFIX).concat(index, ".png"))) {
1071
+ index++;
1072
+ }
1073
+ return "".concat(PDF_IMAGE_PREFIX).concat(index, ".png");
1074
+ }
1075
+ /**
1076
+ * Sets each text's width factor so it spans its PDF advance width in the
1077
+ * font the viewer will actually draw it with (usually a substitute for the
1078
+ * PDF font). Texts whose glyphs cannot be measured keep the PDF factor.
1079
+ */
1080
+ function fitTextWidths(db, texts, scale) {
1081
+ return __awaiter(this, void 0, void 0, function () {
1082
+ var styleTable, fontsOf, fontNames, texts_2, texts_2_1, entity, _a, font, bigFont, err_3, texts_3, texts_3_1, _b, entity, run, _c, font, bigFont, natural;
1083
+ var e_10, _d, e_11, _e;
1084
+ return __generator(this, function (_f) {
1085
+ switch (_f.label) {
1086
+ case 0:
1087
+ styleTable = db.tables.textStyleTable;
1088
+ fontsOf = function (entity) {
1089
+ var _a, _b;
1090
+ var style = styleTable.resolveAt(entity.styleName || db.textstyle);
1091
+ return {
1092
+ font: (_a = style === null || style === void 0 ? void 0 : style.textStyle.font) !== null && _a !== void 0 ? _a : '',
1093
+ bigFont: (_b = style === null || style === void 0 ? void 0 : style.textStyle.bigFont) !== null && _b !== void 0 ? _b : ''
1094
+ };
1095
+ };
1096
+ fontNames = new Set();
1097
+ try {
1098
+ for (texts_2 = __values(texts), texts_2_1 = texts_2.next(); !texts_2_1.done; texts_2_1 = texts_2.next()) {
1099
+ entity = texts_2_1.value.entity;
1100
+ _a = fontsOf(entity), font = _a.font, bigFont = _a.bigFont;
1101
+ if (font)
1102
+ fontNames.add(font);
1103
+ if (bigFont)
1104
+ fontNames.add(bigFont);
1105
+ }
1106
+ }
1107
+ catch (e_10_1) { e_10 = { error: e_10_1 }; }
1108
+ finally {
1109
+ try {
1110
+ if (texts_2_1 && !texts_2_1.done && (_d = texts_2.return)) _d.call(texts_2);
1111
+ }
1112
+ finally { if (e_10) throw e_10.error; }
1113
+ }
1114
+ _f.label = 1;
1115
+ case 1:
1116
+ _f.trys.push([1, 3, , 4]);
1117
+ return [4 /*yield*/, AcApFontUtil.prepareTextMeasurement(__spreadArray([], __read(fontNames), false))];
1118
+ case 2:
1119
+ _f.sent();
1120
+ return [3 /*break*/, 4];
1121
+ case 3:
1122
+ err_3 = _f.sent();
1123
+ // Without fonts there is nothing to measure against; keep PDF factors.
1124
+ log.warn('[PdfImport] Could not load fonts to fit text widths:', err_3);
1125
+ return [2 /*return*/];
1126
+ case 4:
1127
+ try {
1128
+ for (texts_3 = __values(texts), texts_3_1 = texts_3.next(); !texts_3_1.done; texts_3_1 = texts_3.next()) {
1129
+ _b = texts_3_1.value, entity = _b.entity, run = _b.run;
1130
+ if (run.width === undefined)
1131
+ continue;
1132
+ _c = fontsOf(entity), font = _c.font, bigFont = _c.bigFont;
1133
+ natural = AcApFontUtil.measureTextWidth(entity.textString, font, entity.height, bigFont);
1134
+ entity.widthFactor = acapPdfFitWidthFactor(entity.widthFactor, run.width * scale, natural);
1135
+ }
1136
+ }
1137
+ catch (e_11_1) { e_11 = { error: e_11_1 }; }
1138
+ finally {
1139
+ try {
1140
+ if (texts_3_1 && !texts_3_1.done && (_e = texts_3.return)) _e.call(texts_3);
1141
+ }
1142
+ finally { if (e_11) throw e_11.error; }
1143
+ }
1144
+ return [2 /*return*/];
1145
+ }
1146
+ });
1147
+ });
1148
+ }
1149
+ /** Creates the CAD entity for a recognized shape. */
1150
+ /**
1151
+ * Distance (paper millimeters, before import scaling) within which a stroke
1152
+ * counts as lying on a recognized hatch line. PDF writers round coordinates
1153
+ * to about 0.01 pt (0.0035 mm), so this leaves ample headroom while staying
1154
+ * far below any real hatch spacing.
1155
+ */
1156
+ var PDF_HATCH_TOLERANCE_MM = 0.05;
1157
+ function createPatternHatch(db, found) {
1158
+ var loops = found.boundary
1159
+ .map(function (shape) { return acapPdfShapeToLoop(shape); })
1160
+ .filter(function (loop) { return !!loop; });
1161
+ var hatch = acapPdfCreatePatternHatch(db, loops, found.pattern, found.definitionLines);
1162
+ if (!hatch)
1163
+ return undefined;
1164
+ if (found.layerName)
1165
+ hatch.layer = found.layerName;
1166
+ applyPdfColor(hatch, found.color);
1167
+ return hatch;
1168
+ }
1169
+ function shapeToEntity(shape) {
1170
+ switch (shape.kind) {
1171
+ case 'line':
1172
+ return new AcDbLine(new AcGePoint3d(shape.start.x, shape.start.y, 0), new AcGePoint3d(shape.end.x, shape.end.y, 0));
1173
+ case 'circle':
1174
+ return new AcDbCircle(new AcGePoint3d(shape.center.x, shape.center.y, 0), shape.radius);
1175
+ case 'arc':
1176
+ return new AcDbArc(new AcGePoint3d(shape.center.x, shape.center.y, 0), shape.radius, shape.startAngle, shape.endAngle);
1177
+ case 'ellipse': {
1178
+ var major = Math.hypot(shape.majorAxis.x, shape.majorAxis.y);
1179
+ if (!(major > 0))
1180
+ return null;
1181
+ return new AcDbEllipse(new AcGePoint3d(shape.center.x, shape.center.y, 0), AcGeVector3d.Z_AXIS, new AcGeVector3d(shape.majorAxis.x, shape.majorAxis.y, 0), major, major * shape.radiusRatio, shape.startAngle, shape.endAngle);
1182
+ }
1183
+ case 'polyline': {
1184
+ if (shape.vertices.length < 2)
1185
+ return null;
1186
+ var poly_1 = new AcDbPolyline();
1187
+ shape.vertices.forEach(function (v, i) {
1188
+ return poly_1.addVertexAt(i, new AcGePoint2d(v.x, v.y), v.bulge);
1189
+ });
1190
+ poly_1.closed = shape.closed;
1191
+ return poly_1;
1192
+ }
1193
+ case 'spline':
1194
+ try {
1195
+ return new AcDbSpline(shape.controlPoints.map(function (p) { return new AcGePoint3d(p.x, p.y, 0); }), shape.knots);
1196
+ }
1197
+ catch (err) {
1198
+ log.warn('[PdfImport] Skipped invalid spline:', err);
1199
+ return null;
1200
+ }
1201
+ }
1202
+ }
1203
+ /** Standard AutoCAD line weights in 1/100 mm. */
1204
+ var STANDARD_LINE_WEIGHTS = [
1205
+ 0, 5, 9, 13, 15, 18, 20, 25, 30, 35, 40, 50, 53, 60, 70, 80, 90, 100, 106,
1206
+ 120, 140, 158, 200, 211
1207
+ ];
1208
+ /** Maps a stroke width in millimeters to the nearest standard line weight. */
1209
+ function nearestLineWeight(widthMm) {
1210
+ var e_12, _a;
1211
+ var hundredths = widthMm * 100;
1212
+ var best = STANDARD_LINE_WEIGHTS[0];
1213
+ try {
1214
+ for (var STANDARD_LINE_WEIGHTS_1 = __values(STANDARD_LINE_WEIGHTS), STANDARD_LINE_WEIGHTS_1_1 = STANDARD_LINE_WEIGHTS_1.next(); !STANDARD_LINE_WEIGHTS_1_1.done; STANDARD_LINE_WEIGHTS_1_1 = STANDARD_LINE_WEIGHTS_1.next()) {
1215
+ var weight = STANDARD_LINE_WEIGHTS_1_1.value;
1216
+ if (Math.abs(weight - hundredths) < Math.abs(best - hundredths)) {
1217
+ best = weight;
1218
+ }
1219
+ }
1220
+ }
1221
+ catch (e_12_1) { e_12 = { error: e_12_1 }; }
1222
+ finally {
1223
+ try {
1224
+ if (STANDARD_LINE_WEIGHTS_1_1 && !STANDARD_LINE_WEIGHTS_1_1.done && (_a = STANDARD_LINE_WEIGHTS_1.return)) _a.call(STANDARD_LINE_WEIGHTS_1);
1225
+ }
1226
+ finally { if (e_12) throw e_12.error; }
1227
+ }
1228
+ return best;
1229
+ }
1230
+ /** PDF font name for a `setFont` resource id, when PDF.js loaded it. */
1231
+ function pdfFontName(page, fontId) {
1232
+ try {
1233
+ if (!page.commonObjs.has(fontId))
1234
+ return undefined;
1235
+ var font = page.commonObjs.get(fontId);
1236
+ return typeof (font === null || font === void 0 ? void 0 : font.name) === 'string' && font.name ? font.name : undefined;
1237
+ }
1238
+ catch (_a) {
1239
+ return undefined;
1240
+ }
1241
+ }
1242
+ /** Name prefix for blocks recovered from repeated Form XObjects. */
1243
+ var PDF_FORM_BLOCK_PREFIX = 'PDF_FORM_';
1244
+ /** First `<prefix><n>` block name not used in the drawing. */
1245
+ function uniqueBlockName(context, prefix) {
1246
+ var blockTable = context.doc.database.tables.blockTable;
1247
+ var index = 1;
1248
+ while (blockTable.has("".concat(prefix).concat(index)))
1249
+ index++;
1250
+ return "".concat(prefix).concat(index);
1251
+ }
365
1252
  function applyPdfColor(entity, color) {
366
1253
  if (!color)
367
1254
  return;
1255
+ if (color === PDF_IMPORT_FOREGROUND_COLOR) {
1256
+ entity.color = new AcCmColor().setForeground();
1257
+ return;
1258
+ }
368
1259
  var match = /^#([0-9a-fA-F]{6})$/.exec(color);
369
1260
  if (!match)
370
1261
  return;