@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.
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
@@ -43,11 +43,140 @@ var __read = (this && this.__read) || function (o, n) {
43
43
  }
44
44
  return ar;
45
45
  };
46
+ var __spreadArray = (this && this.__spreadArray) || function (to, from, pack) {
47
+ if (pack || arguments.length === 2) for (var i = 0, l = from.length, ar; i < l; i++) {
48
+ if (ar || !(i in from)) {
49
+ if (!ar) ar = Array.prototype.slice.call(from, 0, i);
50
+ ar[i] = from[i];
51
+ }
52
+ }
53
+ return to.concat(ar || Array.prototype.slice.call(from));
54
+ };
46
55
  import { getPdfMarkedContentTarget } from './pdfOptionalContent';
47
56
  /** 1 PDF point in mm (1 pt = 1/72 inch = 25.4/72 mm) */
48
57
  export var PDF_PT_TO_MM = 25.4 / 72;
49
58
  /** Bezier approximation resolution (line segments per curve) */
50
59
  var BEZIER_STEPS = 8;
60
+ /**
61
+ * Sentinel colour: CAD ACI 7 (AutoCAD “foreground” / auto-contrast).
62
+ *
63
+ * Renders white on a dark CAD canvas and black on a light one.
64
+ */
65
+ export var PDF_IMPORT_FOREGROUND_COLOR = 'foreground';
66
+ /**
67
+ * Channel ceiling for near-black ink. All RGB components must be below this
68
+ * so CAD primaries (`#0000ff`, …) are not treated as paper black. High
69
+ * enough for the "rich black" design tools emit after CMYK conversion
70
+ * (e.g. `#2c2e35`), which is unreadable on a dark CAD canvas.
71
+ */
72
+ var PDF_PAPER_BLACK_CHANNEL = 64;
73
+ /**
74
+ * Channel floor for near-white ink (dark-paper drawings).
75
+ */
76
+ var PDF_PAPER_WHITE_CHANNEL = 208;
77
+ function parseCssRgb(color) {
78
+ if (!color || !/^#[0-9a-fA-F]{6}$/.test(color))
79
+ return undefined;
80
+ var value = Number.parseInt(color.slice(1), 16);
81
+ return {
82
+ r: (value >> 16) & 255,
83
+ g: (value >> 8) & 255,
84
+ b: value & 255
85
+ };
86
+ }
87
+ /** True when every channel is near black (paper ink on white PDF). */
88
+ export function isPdfNearBlackColor(color) {
89
+ var rgb = parseCssRgb(color);
90
+ if (!rgb)
91
+ return false;
92
+ return (rgb.r < PDF_PAPER_BLACK_CHANNEL &&
93
+ rgb.g < PDF_PAPER_BLACK_CHANNEL &&
94
+ rgb.b < PDF_PAPER_BLACK_CHANNEL);
95
+ }
96
+ /** True when every channel is near white (paper ink on dark PDF). */
97
+ export function isPdfNearWhiteColor(color) {
98
+ var rgb = parseCssRgb(color);
99
+ if (!rgb)
100
+ return false;
101
+ return (rgb.r > PDF_PAPER_WHITE_CHANNEL &&
102
+ rgb.g > PDF_PAPER_WHITE_CHANNEL &&
103
+ rgb.b > PDF_PAPER_WHITE_CHANNEL);
104
+ }
105
+ /**
106
+ * Infers PDF paper tone from painted colours.
107
+ *
108
+ * Dark paper is rare; bias toward light so white fills on a normal CAD PDF
109
+ * do not leave near-black linework unmapped (and invisible on a dark canvas).
110
+ * Only classify as dark when near-white ink dominates and near-black is absent.
111
+ */
112
+ export function detectPdfImportPaperTone(colors) {
113
+ var e_1, _a;
114
+ var nearBlack = 0;
115
+ var nearWhite = 0;
116
+ try {
117
+ for (var colors_1 = __values(colors), colors_1_1 = colors_1.next(); !colors_1_1.done; colors_1_1 = colors_1.next()) {
118
+ var color = colors_1_1.value;
119
+ if (isPdfNearBlackColor(color))
120
+ nearBlack++;
121
+ else if (isPdfNearWhiteColor(color))
122
+ nearWhite++;
123
+ }
124
+ }
125
+ catch (e_1_1) { e_1 = { error: e_1_1 }; }
126
+ finally {
127
+ try {
128
+ if (colors_1_1 && !colors_1_1.done && (_a = colors_1.return)) _a.call(colors_1);
129
+ }
130
+ finally { if (e_1) throw e_1.error; }
131
+ }
132
+ if (nearBlack === 0 && nearWhite >= 8)
133
+ return 'dark';
134
+ return 'light';
135
+ }
136
+ /**
137
+ * Maps PDF contrast ink to ACI 7 (`foreground`) based on paper tone.
138
+ *
139
+ * - Light paper + near-black → {@link PDF_IMPORT_FOREGROUND_COLOR}
140
+ * - Dark paper + near-white → {@link PDF_IMPORT_FOREGROUND_COLOR}
141
+ * - Other colours kept as lowercase `#rrggbb`
142
+ */
143
+ export function remapPdfImportColor(color, paperTone) {
144
+ if (paperTone === void 0) { paperTone = 'light'; }
145
+ if (!color)
146
+ return color;
147
+ if (color === PDF_IMPORT_FOREGROUND_COLOR)
148
+ return color;
149
+ if (!parseCssRgb(color))
150
+ return color;
151
+ if (paperTone === 'light' && isPdfNearBlackColor(color)) {
152
+ return PDF_IMPORT_FOREGROUND_COLOR;
153
+ }
154
+ if (paperTone === 'dark' && isPdfNearWhiteColor(color)) {
155
+ return PDF_IMPORT_FOREGROUND_COLOR;
156
+ }
157
+ return color.toLowerCase();
158
+ }
159
+ /**
160
+ * Applies contrast-ink remapping to an extracted page.
161
+ *
162
+ * When `paperTone` is `'auto'`, tone is detected from the raw colours first.
163
+ */
164
+ export function applyPdfImportContrastColors(content, options) {
165
+ var _a;
166
+ var enabled = (options === null || options === void 0 ? void 0 : options.remapContrastInk) !== false && (options === null || options === void 0 ? void 0 : options.remapDarkColors) !== false;
167
+ if (!enabled)
168
+ return content;
169
+ var requested = (_a = options === null || options === void 0 ? void 0 : options.paperTone) !== null && _a !== void 0 ? _a : 'auto';
170
+ var tone = requested === 'auto'
171
+ ? detectPdfImportPaperTone(__spreadArray(__spreadArray([], __read(content.subpaths.map(function (s) { return s.color; })), false), __read(content.texts.map(function (t) { return t.color; })), false))
172
+ : requested;
173
+ return {
174
+ subpaths: content.subpaths.map(function (subpath) { return (__assign(__assign(__assign({}, subpath), { color: remapPdfImportColor(subpath.color, tone) }), (subpath.fillColor
175
+ ? { fillColor: remapPdfImportColor(subpath.fillColor, tone) }
176
+ : {}))); }),
177
+ texts: content.texts.map(function (text) { return (__assign(__assign({}, text), { color: remapPdfImportColor(text.color, tone) })); })
178
+ };
179
+ }
51
180
  /**
52
181
  * Converts one page operator list into model-space subpaths.
53
182
  *
@@ -59,12 +188,15 @@ var BEZIER_STEPS = 8;
59
188
  * @param fallbackLayerName - Layer for geometry outside a single OCG. Omit it
60
189
  * for PDFs with no optional content so entities stay on the current layer.
61
190
  */
62
- export function extractPdfImportSubpaths(opList, ops, viewport, ocgLayers, fallbackLayerName) {
63
- var e_1, _a;
64
- var _b, _c, _d;
191
+ export function extractPdfImportSubpaths(opList, ops, viewport, ocgLayers, fallbackLayerName, options) {
192
+ var e_2, _a;
193
+ var _b, _c;
65
194
  var fnArray = opList.fnArray, argsArray = opList.argsArray;
66
195
  var subpathResult = [];
196
+ var formInstances = [];
197
+ var currentFormInstance;
67
198
  var textResult = [];
199
+ var imageResult = [];
68
200
  // PDF.js 5.x normally packs path construction into OPS.constructPath.
69
201
  // The packed stream uses DrawOPS values from PDF.js shared/util:
70
202
  // moveTo=0, lineTo=1, curveTo=2, quadraticCurveTo=3, closePath=4.
@@ -75,24 +207,76 @@ export function extractPdfImportSubpaths(opList, ops, viewport, ocgLayers, fallb
75
207
  var DRAW_CLOSE_PATH = 4;
76
208
  var subpaths = [];
77
209
  var current = [];
210
+ var currentSegments = [];
78
211
  var currentPathLayerName = fallbackLayerName;
79
212
  var activeLayerName = fallbackLayerName;
213
+ // True while inside an OCG that starts hidden. Viewers draw nested optional
214
+ // content only when every enclosing group is ON, so an inner ON group (e.g.
215
+ // a frozen INSERT's children on their own layers) must not pull geometry
216
+ // out of the hidden outer layer.
217
+ var activeLayerHidden = false;
80
218
  var markedContentLayerStack = [];
81
219
  var curX = 0;
82
220
  var curY = 0;
221
+ // Start of the current subpath in user space: `h` returns the current
222
+ // point there, so a following `l` without `m` starts from it.
223
+ var startX = 0;
224
+ var startY = 0;
83
225
  var ctm = [1, 0, 0, 1, 0, 0];
84
226
  var fillColor = '#000000';
85
227
  var strokeColor = '#000000';
228
+ var lineWidth = 1;
229
+ var dashArray = [];
230
+ // Innermost clip in effect (graphics state) and whether `W` is pending.
231
+ var clipId;
232
+ var pendingClip = false;
233
+ var clipPaths = [];
86
234
  // Text state parameters (Tf/Tc/Tw/Tz/TL/Tr/Ts) are graphics-state fields and
87
235
  // must round-trip with q/Q. Tm/Tlm and the text cursor are not.
88
236
  var fontSize = 0;
237
+ var fontId;
89
238
  var textHScale = 1;
90
239
  var textRise = 0;
91
240
  var leading = 0;
92
241
  var charSpacing = 0;
93
242
  var wordSpacing = 0;
94
243
  var textRenderingMode = 0;
244
+ var snapshotGraphicsState = function () { return ({
245
+ ctm: cloneMatrix(ctm),
246
+ fillColor: fillColor,
247
+ strokeColor: strokeColor,
248
+ lineWidth: lineWidth,
249
+ dashArray: dashArray,
250
+ clipId: clipId,
251
+ fontSize: fontSize,
252
+ fontId: fontId,
253
+ textHScale: textHScale,
254
+ textRise: textRise,
255
+ leading: leading,
256
+ charSpacing: charSpacing,
257
+ wordSpacing: wordSpacing,
258
+ textRenderingMode: textRenderingMode
259
+ }); };
260
+ var restoreGraphicsState = function (restored) {
261
+ ctm = restored.ctm;
262
+ fillColor = restored.fillColor;
263
+ strokeColor = restored.strokeColor;
264
+ lineWidth = restored.lineWidth;
265
+ dashArray = restored.dashArray;
266
+ clipId = restored.clipId;
267
+ fontSize = restored.fontSize;
268
+ fontId = restored.fontId;
269
+ textHScale = restored.textHScale;
270
+ textRise = restored.textRise;
271
+ leading = restored.leading;
272
+ charSpacing = restored.charSpacing;
273
+ wordSpacing = restored.wordSpacing;
274
+ textRenderingMode = restored.textRenderingMode;
275
+ };
276
+ // q/Q stack — separate from Form XObject Begin/End so unbalanced save/restore
277
+ // inside a form cannot pop the form entry (or vice versa).
95
278
  var graphicsStack = [];
279
+ var formStack = [];
96
280
  var textMatrix = [1, 0, 0, 1, 0, 0];
97
281
  var textLineMatrix = [1, 0, 0, 1, 0, 0];
98
282
  var textX = 0;
@@ -119,38 +303,163 @@ export function extractPdfImportSubpaths(opList, ops, viewport, ocgLayers, fallb
119
303
  }); };
120
304
  var flush = function () {
121
305
  if (current.length > 1) {
122
- subpaths.push({
306
+ var subpath = {
123
307
  points: current,
308
+ segments: currentSegments,
124
309
  layerName: currentPathLayerName
125
- });
310
+ };
311
+ if (currentFormInstance !== undefined) {
312
+ subpath.formInstance = currentFormInstance;
313
+ }
314
+ if (clipId !== undefined)
315
+ subpath.clipPath = clipId;
316
+ subpaths.push(subpath);
126
317
  }
127
318
  current = [];
319
+ currentSegments = [];
128
320
  currentPathLayerName = activeLayerName;
129
321
  };
130
- var commit = function (color) {
131
- var e_2, _a;
132
- if (color === void 0) { color = strokeColor; }
133
- flush();
322
+ var samePoint = function (a, b) {
323
+ return a.x === b.x && a.y === b.y;
324
+ };
325
+ var closeOpenSubpaths = function () {
326
+ var e_3, _a;
327
+ var _b;
328
+ // PDF fill/eoFill implicitly close each open subpath; pdf.js does not
329
+ // always emit DrawOPS.closePath for plain fill paints.
330
+ if (current.length > 0) {
331
+ var first = current[0];
332
+ var last = current[current.length - 1];
333
+ if (!samePoint(first, last)) {
334
+ current.push(__assign({}, first));
335
+ currentSegments.push({ kind: 'line', p0: last, p1: __assign({}, first) });
336
+ }
337
+ flush();
338
+ }
134
339
  try {
135
340
  for (var subpaths_1 = __values(subpaths), subpaths_1_1 = subpaths_1.next(); !subpaths_1_1.done; subpaths_1_1 = subpaths_1.next()) {
136
341
  var subpath = subpaths_1_1.value;
137
- subpathResult.push(__assign(__assign({}, subpath), { color: color }));
342
+ var pts = subpath.points;
343
+ if (pts.length < 2)
344
+ continue;
345
+ var first = pts[0];
346
+ var last = pts[pts.length - 1];
347
+ if (!samePoint(first, last)) {
348
+ pts.push(__assign({}, first));
349
+ (_b = subpath.segments) === null || _b === void 0 ? void 0 : _b.push({ kind: 'line', p0: last, p1: __assign({}, first) });
350
+ }
138
351
  }
139
352
  }
140
- catch (e_2_1) { e_2 = { error: e_2_1 }; }
353
+ catch (e_3_1) { e_3 = { error: e_3_1 }; }
141
354
  finally {
142
355
  try {
143
356
  if (subpaths_1_1 && !subpaths_1_1.done && (_a = subpaths_1.return)) _a.call(subpaths_1);
144
357
  }
145
- finally { if (e_2) throw e_2.error; }
358
+ finally { if (e_3) throw e_3.error; }
359
+ }
360
+ };
361
+ var paintCount = 0;
362
+ var commit = function (color, filled, stroked) {
363
+ var e_4, _a;
364
+ if (color === void 0) { color = strokeColor; }
365
+ if (filled === void 0) { filled = false; }
366
+ if (stroked === void 0) { stroked = !filled; }
367
+ flush();
368
+ var width = stroked ? strokeWidthMm() : 0;
369
+ var dashes = stroked ? dashPatternMm() : undefined;
370
+ var group = paintCount++;
371
+ try {
372
+ for (var subpaths_2 = __values(subpaths), subpaths_2_1 = subpaths_2.next(); !subpaths_2_1.done; subpaths_2_1 = subpaths_2.next()) {
373
+ var subpath = subpaths_2_1.value;
374
+ var result = __assign(__assign({}, subpath), { color: color });
375
+ if (filled) {
376
+ result.filled = true;
377
+ result.fillColor = fillColor;
378
+ result.paintGroup = group;
379
+ if (stroked)
380
+ result.stroked = true;
381
+ }
382
+ if (width > 0)
383
+ result.lineWidth = width;
384
+ if (dashes)
385
+ result.dashPattern = dashes;
386
+ subpathResult.push(result);
387
+ }
388
+ }
389
+ catch (e_4_1) { e_4 = { error: e_4_1 }; }
390
+ finally {
391
+ try {
392
+ if (subpaths_2_1 && !subpaths_2_1.done && (_a = subpaths_2.return)) _a.call(subpaths_2);
393
+ }
394
+ finally { if (e_4) throw e_4.error; }
146
395
  }
147
396
  subpaths = [];
148
397
  };
398
+ // Dash lengths are in user space like the line width. PDF repeats an odd
399
+ // array to even length ([3] means 3 on, 3 off). All-zero arrays are solid.
400
+ var dashPatternMm = function () {
401
+ if (dashArray.length === 0 || dashArray.every(function (v) { return !(v > 0); })) {
402
+ return undefined;
403
+ }
404
+ var scale = Math.sqrt(Math.abs(ctm[0] * ctm[3] - ctm[1] * ctm[2])) * PDF_PT_TO_MM;
405
+ var even = dashArray.length % 2 === 0 ? dashArray : __spreadArray(__spreadArray([], __read(dashArray), false), __read(dashArray), false);
406
+ return even.map(function (v) { return Math.max(0, v) * scale; });
407
+ };
408
+ // PDF line width is in user space; the CTM scales it to page points. Use
409
+ // the geometric mean of the axis scales, which is exact for similarity
410
+ // transforms and a reasonable average for skewed ones.
411
+ var strokeWidthMm = function () {
412
+ if (!(lineWidth > 0))
413
+ return 0;
414
+ var scale = Math.sqrt(Math.abs(ctm[0] * ctm[3] - ctm[1] * ctm[2]));
415
+ return lineWidth * scale * PDF_PT_TO_MM;
416
+ };
417
+ var isStrokePaint = function (paintOp) {
418
+ return paintOp === ops.stroke ||
419
+ paintOp === ops.closeStroke ||
420
+ paintOp === ops.fillStroke ||
421
+ paintOp === ops.eoFillStroke ||
422
+ paintOp === ops.closeFillStroke ||
423
+ paintOp === ops.closeEOFillStroke;
424
+ };
425
+ var isFillPaint = function (paintOp) {
426
+ return paintOp === ops.fill ||
427
+ paintOp === ops.eoFill ||
428
+ paintOp === ops.fillStroke ||
429
+ paintOp === ops.eoFillStroke ||
430
+ paintOp === ops.closeFillStroke ||
431
+ paintOp === ops.closeEOFillStroke ||
432
+ (ops.rawFillPath !== undefined && paintOp === ops.rawFillPath);
433
+ };
149
434
  var paintColor = function (paintOp) {
150
- return paintOp === ops.fill || paintOp === ops.eoFill ? fillColor : strokeColor;
435
+ if (paintOp === ops.fill ||
436
+ paintOp === ops.eoFill ||
437
+ (ops.rawFillPath !== undefined && paintOp === ops.rawFillPath)) {
438
+ return fillColor;
439
+ }
440
+ return strokeColor;
441
+ };
442
+ // `W` / `W*` make the path of the next paint operator the clip.
443
+ var captureClip = function () {
444
+ if (!pendingClip)
445
+ return;
446
+ pendingClip = false;
447
+ flush();
448
+ var loops = subpaths
449
+ .map(function (subpath) {
450
+ var pts = subpath.points;
451
+ var closed = pts.length > 1 && samePoint(pts[0], pts[pts.length - 1]);
452
+ return closed ? pts.slice(0, -1) : __spreadArray([], __read(pts), false);
453
+ })
454
+ .filter(function (loop) { return loop.length >= 3; });
455
+ if (loops.length === 0)
456
+ return;
457
+ clipPaths.push(loops);
458
+ clipId = clipPaths.length - 1;
151
459
  };
152
460
  var discard = function () {
153
461
  current = [];
462
+ currentSegments = [];
154
463
  subpaths = [];
155
464
  currentPathLayerName = activeLayerName;
156
465
  };
@@ -164,20 +473,35 @@ export function extractPdfImportSubpaths(opList, ops, viewport, ocgLayers, fallb
164
473
  };
165
474
  var tx = function (x, y) { return pagePointToCadPoint(x, y).x; };
166
475
  var ty = function (x, y) { return pagePointToCadPoint(x, y).y; };
476
+ var lastCadPoint = function () {
477
+ return current.length > 0
478
+ ? current[current.length - 1]
479
+ : pagePointToCadPoint(curX, curY);
480
+ };
167
481
  var moveTo = function (x, y) {
168
482
  flush();
169
483
  curX = x;
170
484
  curY = y;
485
+ startX = x;
486
+ startY = y;
171
487
  currentPathLayerName = activeLayerName;
172
488
  current = [{ x: tx(x, y), y: ty(x, y) }];
173
489
  };
174
490
  var lineTo = function (x, y) {
491
+ var p0 = lastCadPoint();
492
+ if (current.length === 0)
493
+ current.push(p0);
175
494
  curX = x;
176
495
  curY = y;
177
- current.push({ x: tx(x, y), y: ty(x, y) });
496
+ var p1 = pagePointToCadPoint(x, y);
497
+ current.push(p1);
498
+ currentSegments.push({ kind: 'line', p0: p0, p1: p1 });
178
499
  };
179
500
  var curveTo = function (x1, y1, x2, y2, x3, y3) {
180
- var e_3, _a;
501
+ var e_5, _a;
502
+ var p0 = lastCadPoint();
503
+ if (current.length === 0)
504
+ current.push(p0);
181
505
  var pts = cubicBezier({ x: curX, y: curY }, { x: x1, y: y1 }, { x: x2, y: y2 }, { x: x3, y: y3 }, BEZIER_STEPS);
182
506
  try {
183
507
  for (var pts_1 = __values(pts), pts_1_1 = pts_1.next(); !pts_1_1.done; pts_1_1 = pts_1.next()) {
@@ -185,17 +509,33 @@ export function extractPdfImportSubpaths(opList, ops, viewport, ocgLayers, fallb
185
509
  current.push({ x: tx(point.x, point.y), y: ty(point.x, point.y) });
186
510
  }
187
511
  }
188
- catch (e_3_1) { e_3 = { error: e_3_1 }; }
512
+ catch (e_5_1) { e_5 = { error: e_5_1 }; }
189
513
  finally {
190
514
  try {
191
515
  if (pts_1_1 && !pts_1_1.done && (_a = pts_1.return)) _a.call(pts_1);
192
516
  }
193
- finally { if (e_3) throw e_3.error; }
517
+ finally { if (e_5) throw e_5.error; }
194
518
  }
519
+ // Reuse the last sampled point as p3 so segments and points share the
520
+ // exact same end coordinate.
521
+ currentSegments.push({
522
+ kind: 'cubic',
523
+ p0: p0,
524
+ p1: pagePointToCadPoint(x1, y1),
525
+ p2: pagePointToCadPoint(x2, y2),
526
+ p3: current[current.length - 1]
527
+ });
195
528
  curX = x3;
196
529
  curY = y3;
197
530
  };
198
531
  var quadraticCurveTo = function (x1, y1, x2, y2) {
532
+ var p0 = lastCadPoint();
533
+ if (current.length === 0)
534
+ current.push(p0);
535
+ // Degree elevation: a quadratic is the cubic with controls 2/3 of the way
536
+ // from each end point toward the single quadratic control.
537
+ var c1 = pagePointToCadPoint(curX + (2 / 3) * (x1 - curX), curY + (2 / 3) * (y1 - curY));
538
+ var c2 = pagePointToCadPoint(x2 + (2 / 3) * (x1 - x2), y2 + (2 / 3) * (y1 - y2));
199
539
  for (var step = 1; step <= BEZIER_STEPS; step++) {
200
540
  var t = step / BEZIER_STEPS;
201
541
  var mt = 1 - t;
@@ -203,13 +543,27 @@ export function extractPdfImportSubpaths(opList, ops, viewport, ocgLayers, fallb
203
543
  var y = mt * mt * curY + 2 * mt * t * y1 + t * t * y2;
204
544
  current.push({ x: tx(x, y), y: ty(x, y) });
205
545
  }
546
+ currentSegments.push({
547
+ kind: 'cubic',
548
+ p0: p0,
549
+ p1: c1,
550
+ p2: c2,
551
+ p3: current[current.length - 1]
552
+ });
206
553
  curX = x2;
207
554
  curY = y2;
208
555
  };
209
556
  var closePath = function () {
210
557
  if (current.length > 0) {
211
- current.push(__assign({}, current[0]));
558
+ var first = current[0];
559
+ var last = current[current.length - 1];
560
+ current.push(__assign({}, first));
561
+ if (!samePoint(first, last)) {
562
+ currentSegments.push({ kind: 'line', p0: last, p1: __assign({}, first) });
563
+ }
212
564
  }
565
+ curX = startX;
566
+ curY = startY;
213
567
  flush();
214
568
  };
215
569
  var rectangle = function (x, y, width, height) {
@@ -246,7 +600,8 @@ export function extractPdfImportSubpaths(opList, ops, viewport, ocgLayers, fallb
246
600
  closePath();
247
601
  break;
248
602
  default:
249
- // Avoid consuming coordinates with an unknown DrawOPS value.
603
+ // Unknown DrawOPS — stop this stream so we do not desync
604
+ // coordinates, but keep geometry already collected for paint.
250
605
  return;
251
606
  }
252
607
  }
@@ -278,6 +633,7 @@ export function extractPdfImportSubpaths(opList, ops, viewport, ocgLayers, fallb
278
633
  curveTo(curX, curY, take(), take(), take(), take());
279
634
  break;
280
635
  case ops.curveTo3: {
636
+ // PDF "y": second control coincides with the end point (x3, y3).
281
637
  var x1 = take();
282
638
  var y1 = take();
283
639
  var x3 = take();
@@ -296,22 +652,36 @@ export function extractPdfImportSubpaths(opList, ops, viewport, ocgLayers, fallb
296
652
  }
297
653
  };
298
654
  var finishConstructPath = function (paintOp) {
299
- switch (paintOp) {
300
- case ops.stroke:
301
- case ops.closeStroke:
302
- case ops.fill:
303
- case ops.eoFill:
304
- case ops.fillStroke:
305
- case ops.eoFillStroke:
306
- case ops.closeFillStroke:
307
- case ops.closeEOFillStroke:
308
- commit(paintColor(paintOp));
309
- break;
310
- case ops.endPath:
311
- // PDF "n" ends the current path without painting it, commonly after
312
- // clipping. Do not create CAD entities from those paths.
313
- discard();
314
- break;
655
+ captureClip();
656
+ if (paintOp === ops.endPath) {
657
+ // PDF "n" ends the current path without painting it, commonly after
658
+ // clipping. Do not create CAD entities from those paths.
659
+ discard();
660
+ return;
661
+ }
662
+ if (paintOp === ops.stroke ||
663
+ paintOp === ops.closeStroke ||
664
+ paintOp === ops.fill ||
665
+ paintOp === ops.eoFill ||
666
+ paintOp === ops.fillStroke ||
667
+ paintOp === ops.eoFillStroke ||
668
+ paintOp === ops.closeFillStroke ||
669
+ paintOp === ops.closeEOFillStroke ||
670
+ (ops.rawFillPath !== undefined && paintOp === ops.rawFillPath)) {
671
+ if (isFillPaint(paintOp)) {
672
+ closeOpenSubpaths();
673
+ }
674
+ else if (paintOp === ops.closeStroke ||
675
+ paintOp === ops.closeFillStroke ||
676
+ paintOp === ops.closeEOFillStroke) {
677
+ closePath();
678
+ }
679
+ commit(paintColor(paintOp), isFillPaint(paintOp), isStrokePaint(paintOp));
680
+ }
681
+ else {
682
+ // Unrecognized paint op — drop the path rather than inventing a stroke
683
+ // at EOF via a trailing commit.
684
+ discard();
315
685
  }
316
686
  };
317
687
  for (var i = 0; i < fnArray.length; i++) {
@@ -319,34 +689,18 @@ export function extractPdfImportSubpaths(opList, ops, viewport, ocgLayers, fallb
319
689
  var value = argsArray[i];
320
690
  var rawArgs = Array.isArray(value) ? value : [];
321
691
  if (fn === ops.save) {
322
- graphicsStack.push({
323
- ctm: cloneMatrix(ctm),
324
- fillColor: fillColor,
325
- strokeColor: strokeColor,
326
- fontSize: fontSize,
327
- textHScale: textHScale,
328
- textRise: textRise,
329
- leading: leading,
330
- charSpacing: charSpacing,
331
- wordSpacing: wordSpacing,
332
- textRenderingMode: textRenderingMode
333
- });
692
+ graphicsStack.push(snapshotGraphicsState());
334
693
  continue;
335
694
  }
336
695
  if (fn === ops.restore) {
337
696
  var restored = graphicsStack.pop();
338
- if (restored) {
339
- ctm = restored.ctm;
340
- fillColor = restored.fillColor;
341
- strokeColor = restored.strokeColor;
342
- fontSize = restored.fontSize;
343
- textHScale = restored.textHScale;
344
- textRise = restored.textRise;
345
- leading = restored.leading;
346
- charSpacing = restored.charSpacing;
347
- wordSpacing = restored.wordSpacing;
348
- textRenderingMode = restored.textRenderingMode;
349
- }
697
+ if (restored)
698
+ restoreGraphicsState(restored);
699
+ continue;
700
+ }
701
+ if ((ops.clip !== undefined && fn === ops.clip) ||
702
+ (ops.eoClip !== undefined && fn === ops.eoClip)) {
703
+ pendingClip = true;
350
704
  continue;
351
705
  }
352
706
  if (fn === ops.setFillRGBColor) {
@@ -355,6 +709,19 @@ export function extractPdfImportSubpaths(opList, ops, viewport, ocgLayers, fallb
355
709
  fillColor = color;
356
710
  continue;
357
711
  }
712
+ if (ops.setDash !== undefined && fn === ops.setDash) {
713
+ var list = asNumberList(rawArgs[0]);
714
+ dashArray = list
715
+ ? Array.from(list, Number).filter(function (v) { return Number.isFinite(v); })
716
+ : [];
717
+ continue;
718
+ }
719
+ if (ops.setLineWidth !== undefined && fn === ops.setLineWidth) {
720
+ var value_1 = Number(rawArgs[0]);
721
+ if (Number.isFinite(value_1) && value_1 >= 0)
722
+ lineWidth = value_1;
723
+ continue;
724
+ }
358
725
  if (fn === ops.setStrokeRGBColor) {
359
726
  var color = readCssColor(rawArgs[0]);
360
727
  if (color)
@@ -375,6 +742,8 @@ export function extractPdfImportSubpaths(opList, ops, viewport, ocgLayers, fallb
375
742
  var size = Number(rawArgs[1]);
376
743
  if (Number.isFinite(size))
377
744
  fontSize = size;
745
+ if (typeof rawArgs[0] === 'string')
746
+ fontId = rawArgs[0];
378
747
  continue;
379
748
  }
380
749
  if (fn === ops.setTextMatrix) {
@@ -402,39 +771,39 @@ export function extractPdfImportSubpaths(opList, ops, viewport, ocgLayers, fallb
402
771
  continue;
403
772
  }
404
773
  if (fn === ops.setLeading) {
405
- var value_1 = Number(rawArgs[0]);
406
- if (Number.isFinite(value_1))
407
- leading = value_1;
408
- continue;
409
- }
410
- if (fn === ops.setCharSpacing) {
411
774
  var value_2 = Number(rawArgs[0]);
412
775
  if (Number.isFinite(value_2))
413
- charSpacing = value_2;
776
+ leading = value_2;
414
777
  continue;
415
778
  }
416
- if (fn === ops.setWordSpacing) {
779
+ if (fn === ops.setCharSpacing) {
417
780
  var value_3 = Number(rawArgs[0]);
418
781
  if (Number.isFinite(value_3))
419
- wordSpacing = value_3;
782
+ charSpacing = value_3;
420
783
  continue;
421
784
  }
422
- if (fn === ops.setHScale) {
785
+ if (fn === ops.setWordSpacing) {
423
786
  var value_4 = Number(rawArgs[0]);
424
787
  if (Number.isFinite(value_4))
425
- textHScale = value_4 / 100;
788
+ wordSpacing = value_4;
426
789
  continue;
427
790
  }
428
- if (fn === ops.setTextRise) {
791
+ if (fn === ops.setHScale) {
429
792
  var value_5 = Number(rawArgs[0]);
430
793
  if (Number.isFinite(value_5))
431
- textRise = value_5;
794
+ textHScale = value_5 / 100;
432
795
  continue;
433
796
  }
434
- if (fn === ops.setTextRenderingMode) {
797
+ if (fn === ops.setTextRise) {
435
798
  var value_6 = Number(rawArgs[0]);
436
799
  if (Number.isFinite(value_6))
437
- textRenderingMode = value_6;
800
+ textRise = value_6;
801
+ continue;
802
+ }
803
+ if (fn === ops.setTextRenderingMode) {
804
+ var value_7 = Number(rawArgs[0]);
805
+ if (Number.isFinite(value_7))
806
+ textRenderingMode = value_7;
438
807
  continue;
439
808
  }
440
809
  if (fn === ops.showText) {
@@ -456,14 +825,25 @@ export function extractPdfImportSubpaths(opList, ops, viewport, ocgLayers, fallb
456
825
  continue;
457
826
  }
458
827
  if (fn === ops.beginMarkedContent) {
459
- markedContentLayerStack.push(activeLayerName);
828
+ markedContentLayerStack.push({
829
+ layerName: activeLayerName,
830
+ hidden: activeLayerHidden
831
+ });
460
832
  continue;
461
833
  }
462
834
  if (fn === ops.beginMarkedContentProps) {
463
- markedContentLayerStack.push(activeLayerName);
835
+ markedContentLayerStack.push({
836
+ layerName: activeLayerName,
837
+ hidden: activeLayerHidden
838
+ });
839
+ if (activeLayerHidden) {
840
+ continue;
841
+ }
464
842
  var target = getPdfMarkedContentTarget(rawArgs);
465
843
  if (target.kind === 'ocg') {
466
- activeLayerName = (_c = (_b = ocgLayers.get(target.id)) === null || _b === void 0 ? void 0 : _b.layerName) !== null && _c !== void 0 ? _c : fallbackLayerName;
844
+ var ocgLayer = ocgLayers.get(target.id);
845
+ activeLayerName = (_b = ocgLayer === null || ocgLayer === void 0 ? void 0 : ocgLayer.layerName) !== null && _b !== void 0 ? _b : fallbackLayerName;
846
+ activeLayerHidden = !!ocgLayer && ocgLayer.visible === false;
467
847
  }
468
848
  else if (target.kind === 'fallback') {
469
849
  activeLayerName = fallbackLayerName;
@@ -471,7 +851,75 @@ export function extractPdfImportSubpaths(opList, ops, viewport, ocgLayers, fallb
471
851
  continue;
472
852
  }
473
853
  if (fn === ops.endMarkedContent) {
474
- activeLayerName = (_d = markedContentLayerStack.pop()) !== null && _d !== void 0 ? _d : fallbackLayerName;
854
+ var outer = markedContentLayerStack.pop();
855
+ activeLayerName = outer ? outer.layerName : fallbackLayerName;
856
+ activeLayerHidden = (_c = outer === null || outer === void 0 ? void 0 : outer.hidden) !== null && _c !== void 0 ? _c : false;
857
+ continue;
858
+ }
859
+ if ((ops.paintImageXObject !== undefined && fn === ops.paintImageXObject) ||
860
+ (ops.paintInlineImageXObject !== undefined &&
861
+ fn === ops.paintInlineImageXObject)) {
862
+ var o = pagePointToCadPoint(0, 0);
863
+ var ux = pagePointToCadPoint(1, 0);
864
+ var uy = pagePointToCadPoint(0, 1);
865
+ var image = {
866
+ toCad: {
867
+ a: ux.x - o.x,
868
+ b: ux.y - o.y,
869
+ c: uy.x - o.x,
870
+ d: uy.y - o.y,
871
+ e: o.x,
872
+ f: o.y
873
+ },
874
+ layerName: activeLayerName
875
+ };
876
+ if (fn === ops.paintImageXObject) {
877
+ if (typeof rawArgs[0] !== 'string')
878
+ continue;
879
+ image.objId = rawArgs[0];
880
+ }
881
+ else {
882
+ if (!rawArgs[0])
883
+ continue;
884
+ image.inline = rawArgs[0];
885
+ }
886
+ imageResult.push(image);
887
+ continue;
888
+ }
889
+ if (ops.paintFormXObjectBegin !== undefined &&
890
+ fn === ops.paintFormXObjectBegin) {
891
+ formStack.push(snapshotGraphicsState());
892
+ var matrix = readMatrix(rawArgs);
893
+ if (matrix) {
894
+ ctm = multiplyMatrix(ctm, matrix);
895
+ }
896
+ if (formStack.length === 1) {
897
+ // Sample the form-space → model-space map; both the CTM and the
898
+ // viewport transform are affine.
899
+ var o = pagePointToCadPoint(0, 0);
900
+ var ux = pagePointToCadPoint(1, 0);
901
+ var uy = pagePointToCadPoint(0, 1);
902
+ formInstances.push({
903
+ toCad: {
904
+ a: ux.x - o.x,
905
+ b: ux.y - o.y,
906
+ c: uy.x - o.x,
907
+ d: uy.y - o.y,
908
+ e: o.x,
909
+ f: o.y
910
+ }
911
+ });
912
+ currentFormInstance = formInstances.length - 1;
913
+ }
914
+ continue;
915
+ }
916
+ if (ops.paintFormXObjectEnd !== undefined &&
917
+ fn === ops.paintFormXObjectEnd) {
918
+ var restored = formStack.pop();
919
+ if (restored)
920
+ restoreGraphicsState(restored);
921
+ if (formStack.length === 0)
922
+ currentFormInstance = undefined;
475
923
  continue;
476
924
  }
477
925
  switch (fn) {
@@ -487,19 +935,19 @@ export function extractPdfImportSubpaths(opList, ops, viewport, ocgLayers, fallb
487
935
  // [paintOp, [Float32Array(DrawOPS + coordinates)], minMax]
488
936
  if (Array.isArray(second)) {
489
937
  try {
490
- for (var second_1 = (e_1 = void 0, __values(second)), second_1_1 = second_1.next(); !second_1_1.done; second_1_1 = second_1.next()) {
938
+ for (var second_1 = (e_2 = void 0, __values(second)), second_1_1 = second_1.next(); !second_1_1.done; second_1_1 = second_1.next()) {
491
939
  var stream = second_1_1.value;
492
940
  if (!isArrayLikePathData(stream))
493
941
  continue;
494
942
  processPackedPathStream(stream);
495
943
  }
496
944
  }
497
- catch (e_1_1) { e_1 = { error: e_1_1 }; }
945
+ catch (e_2_1) { e_2 = { error: e_2_1 }; }
498
946
  finally {
499
947
  try {
500
948
  if (second_1_1 && !second_1_1.done && (_a = second_1.return)) _a.call(second_1);
501
949
  }
502
- finally { if (e_1) throw e_1.error; }
950
+ finally { if (e_2) throw e_2.error; }
503
951
  }
504
952
  }
505
953
  else if (isArrayLikePathData(second)) {
@@ -529,6 +977,7 @@ export function extractPdfImportSubpaths(opList, ops, viewport, ocgLayers, fallb
529
977
  break;
530
978
  }
531
979
  case ops.curveTo3: {
980
+ // PDF "y": second control coincides with the end point.
532
981
  var args = rawArgs;
533
982
  curveTo(args[0], args[1], args[2], args[3], args[2], args[3]);
534
983
  break;
@@ -544,27 +993,47 @@ export function extractPdfImportSubpaths(opList, ops, viewport, ocgLayers, fallb
544
993
  case ops.closeStroke:
545
994
  case ops.closeFillStroke:
546
995
  case ops.closeEOFillStroke:
996
+ captureClip();
547
997
  closePath();
548
- commit(paintColor(fn));
998
+ if (isFillPaint(fn)) {
999
+ closeOpenSubpaths();
1000
+ }
1001
+ commit(paintColor(fn), isFillPaint(fn), isStrokePaint(fn));
549
1002
  break;
550
1003
  case ops.stroke:
1004
+ captureClip();
1005
+ commit(paintColor(fn));
1006
+ break;
551
1007
  case ops.fill:
552
1008
  case ops.eoFill:
553
1009
  case ops.fillStroke:
554
1010
  case ops.eoFillStroke:
555
- commit(paintColor(fn));
1011
+ captureClip();
1012
+ closeOpenSubpaths();
1013
+ commit(paintColor(fn), true, isStrokePaint(fn));
556
1014
  break;
557
1015
  case ops.endPath:
1016
+ captureClip();
558
1017
  discard();
559
1018
  break;
560
1019
  }
561
1020
  }
562
- commit();
563
- return { subpaths: subpathResult, texts: textResult };
1021
+ // Drop any path that never received a paint operator.
1022
+ discard();
1023
+ var content = applyPdfImportContrastColors({ subpaths: subpathResult, texts: textResult }, options);
1024
+ if (formInstances.length > 0)
1025
+ content.formInstances = formInstances;
1026
+ if (clipPaths.length > 0)
1027
+ content.clipPaths = clipPaths;
1028
+ if (imageResult.length > 0)
1029
+ content.images = imageResult;
1030
+ return content;
564
1031
  // Hoisted so the operator loop above can call them.
565
1032
  function moveTextLine(tx, ty) {
1033
+ // Td offsets are in text space: Tlm' = [1 0 0 1 tx ty] × Tlm (row form),
1034
+ // so the shift applies before Tlm and is scaled by the font matrix.
566
1035
  var shift = [1, 0, 0, 1, tx, ty];
567
- textLineMatrix = multiplyMatrix(shift, textLineMatrix);
1036
+ textLineMatrix = multiplyMatrix(textLineMatrix, shift);
568
1037
  textMatrix = cloneMatrix(textLineMatrix);
569
1038
  textX = 0;
570
1039
  textY = 0;
@@ -604,16 +1073,9 @@ export function extractPdfImportSubpaths(opList, ops, viewport, ocgLayers, fallb
604
1073
  var height = Math.hypot(alongY.x - origin_1.x, alongY.y - origin_1.y);
605
1074
  var unitY = fontSize > 0 ? height / fontSize : 0;
606
1075
  var widthFactor = unitY > 1e-9 ? Math.hypot(dx, dy) / unitY : textHScale;
1076
+ var end = textPointToCad(textX + advance * textHScale, textY + textRise);
607
1077
  if (height > 1e-9) {
608
- textResult.push({
609
- text: text,
610
- position: origin_1,
611
- height: height,
612
- rotation: Math.atan2(dy, dx),
613
- widthFactor: widthFactor,
614
- layerName: activeLayerName,
615
- color: (textRenderingMode & 3) === 1 ? strokeColor : fillColor
616
- });
1078
+ textResult.push(__assign({ text: text, position: origin_1, width: Math.hypot(end.x - origin_1.x, end.y - origin_1.y), height: height, rotation: Math.atan2(dy, dx), widthFactor: widthFactor, layerName: activeLayerName, color: (textRenderingMode & 3) === 1 ? strokeColor : fillColor }, (fontId !== undefined ? { fontId: fontId } : {})));
617
1079
  }
618
1080
  }
619
1081
  textX += advance * textHScale;
@@ -641,9 +1103,15 @@ function readCssColor(value) {
641
1103
  return undefined;
642
1104
  }
643
1105
  function readMatrix(rawArgs) {
644
- var nested = rawArgs.length === 1 ? asNumberList(rawArgs[0]) : undefined;
645
- var source = nested && nested.length >= 6 ? nested : rawArgs;
646
- if (source.length < 6)
1106
+ // Text matrix ops pass six numbers (or one Float32Array). Form XObject
1107
+ // begin passes `[matrix, bbox]`, so prefer a nested 6-vector when present.
1108
+ var nested = asNumberList(rawArgs[0]);
1109
+ var source = nested && nested.length >= 6
1110
+ ? nested
1111
+ : rawArgs.length >= 6
1112
+ ? rawArgs
1113
+ : undefined;
1114
+ if (!source || source.length < 6)
647
1115
  return undefined;
648
1116
  return [
649
1117
  Number(source[0]),