@mlightcad/data-model 1.12.0 → 1.12.2

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 (78) hide show
  1. package/README.md +2 -2
  2. package/dist/data-model.cjs +15 -15
  3. package/lib/acis/AcDbAcisDecrypt.d.ts +0 -2
  4. package/lib/acis/AcDbAcisDecrypt.d.ts.map +1 -1
  5. package/lib/acis/AcDbAcisDecrypt.js +0 -2
  6. package/lib/acis/AcDbAcisDecrypt.js.map +1 -1
  7. package/lib/acis/AcDbAcisSab.d.ts.map +1 -1
  8. package/lib/acis/AcDbAcisSab.js +0 -10
  9. package/lib/acis/AcDbAcisSab.js.map +1 -1
  10. package/lib/base/AcDbDxfPairReader.d.ts +5 -4
  11. package/lib/base/AcDbDxfPairReader.d.ts.map +1 -1
  12. package/lib/base/AcDbDxfPairReader.js +60 -19
  13. package/lib/base/AcDbDxfPairReader.js.map +1 -1
  14. package/lib/base/AcDbObject.d.ts +8 -0
  15. package/lib/base/AcDbObject.d.ts.map +1 -1
  16. package/lib/base/AcDbObject.js +22 -3
  17. package/lib/base/AcDbObject.js.map +1 -1
  18. package/lib/base/index.d.ts +1 -1
  19. package/lib/base/index.d.ts.map +1 -1
  20. package/lib/base/index.js +1 -1
  21. package/lib/base/index.js.map +1 -1
  22. package/lib/converter/AcDbBatchProcessing.d.ts +2 -2
  23. package/lib/converter/AcDbBatchProcessing.d.ts.map +1 -1
  24. package/lib/converter/AcDbBatchProcessing.js +15 -16
  25. package/lib/converter/AcDbBatchProcessing.js.map +1 -1
  26. package/lib/converter/worker/AcDbWorkerManager.d.ts.map +1 -1
  27. package/lib/converter/worker/AcDbWorkerManager.js +8 -5
  28. package/lib/converter/worker/AcDbWorkerManager.js.map +1 -1
  29. package/lib/database/AcDbDatabase.d.ts.map +1 -1
  30. package/lib/database/AcDbDatabase.js +27 -11
  31. package/lib/database/AcDbDatabase.js.map +1 -1
  32. package/lib/database/AcDbDatabaseConverterManager.d.ts +7 -2
  33. package/lib/database/AcDbDatabaseConverterManager.d.ts.map +1 -1
  34. package/lib/database/AcDbDatabaseConverterManager.js +9 -2
  35. package/lib/database/AcDbDatabaseConverterManager.js.map +1 -1
  36. package/lib/database/AcDbSysVarManager.d.ts.map +1 -1
  37. package/lib/database/AcDbSysVarManager.js +11 -0
  38. package/lib/database/AcDbSysVarManager.js.map +1 -1
  39. package/lib/database/AcDbSystemVariables.d.ts +7 -1
  40. package/lib/database/AcDbSystemVariables.d.ts.map +1 -1
  41. package/lib/database/AcDbSystemVariables.js +6 -0
  42. package/lib/database/AcDbSystemVariables.js.map +1 -1
  43. package/lib/dxf/AcDbDxfDocumentReader.d.ts +10 -6
  44. package/lib/dxf/AcDbDxfDocumentReader.d.ts.map +1 -1
  45. package/lib/dxf/AcDbDxfDocumentReader.js +12 -19
  46. package/lib/dxf/AcDbDxfDocumentReader.js.map +1 -1
  47. package/lib/dxf/AcDbNativeDxfConverter.d.ts +3 -2
  48. package/lib/dxf/AcDbNativeDxfConverter.d.ts.map +1 -1
  49. package/lib/dxf/AcDbNativeDxfConverter.js +18 -27
  50. package/lib/dxf/AcDbNativeDxfConverter.js.map +1 -1
  51. package/lib/entity/AcDbEntity.d.ts.map +1 -1
  52. package/lib/entity/AcDbEntity.js +6 -16
  53. package/lib/entity/AcDbEntity.js.map +1 -1
  54. package/lib/entity/AcDbOle2Frame.d.ts +11 -0
  55. package/lib/entity/AcDbOle2Frame.d.ts.map +1 -1
  56. package/lib/entity/AcDbOle2Frame.js +20 -0
  57. package/lib/entity/AcDbOle2Frame.js.map +1 -1
  58. package/lib/index.d.ts +2 -3
  59. package/lib/index.d.ts.map +1 -1
  60. package/lib/index.js +2 -5
  61. package/lib/index.js.map +1 -1
  62. package/lib/misc/AcDbOle2FrameGeometry.d.ts +49 -0
  63. package/lib/misc/AcDbOle2FrameGeometry.d.ts.map +1 -0
  64. package/lib/misc/AcDbOle2FrameGeometry.js +66 -0
  65. package/lib/misc/AcDbOle2FrameGeometry.js.map +1 -0
  66. package/lib/misc/AcDbRenderingCache.d.ts +159 -8
  67. package/lib/misc/AcDbRenderingCache.d.ts.map +1 -1
  68. package/lib/misc/AcDbRenderingCache.js +460 -70
  69. package/lib/misc/AcDbRenderingCache.js.map +1 -1
  70. package/lib/misc/index.d.ts +3 -0
  71. package/lib/misc/index.d.ts.map +1 -1
  72. package/lib/misc/index.js +1 -0
  73. package/lib/misc/index.js.map +1 -1
  74. package/package.json +5 -7
  75. package/lib/dxf/registerNativeDxfConverter.d.ts +0 -2
  76. package/lib/dxf/registerNativeDxfConverter.d.ts.map +0 -1
  77. package/lib/dxf/registerNativeDxfConverter.js +0 -12
  78. package/lib/dxf/registerNativeDxfConverter.js.map +0 -1
@@ -1,3 +1,39 @@
1
+ var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) {
2
+ function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); }
3
+ return new (P || (P = Promise))(function (resolve, reject) {
4
+ function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } }
5
+ function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } }
6
+ function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); }
7
+ step((generator = generator.apply(thisArg, _arguments || [])).next());
8
+ });
9
+ };
10
+ var __generator = (this && this.__generator) || function (thisArg, body) {
11
+ var _ = { label: 0, sent: function() { if (t[0] & 1) throw t[1]; return t[1]; }, trys: [], ops: [] }, f, y, t, g;
12
+ return g = { next: verb(0), "throw": verb(1), "return": verb(2) }, typeof Symbol === "function" && (g[Symbol.iterator] = function() { return this; }), g;
13
+ function verb(n) { return function (v) { return step([n, v]); }; }
14
+ function step(op) {
15
+ if (f) throw new TypeError("Generator is already executing.");
16
+ while (g && (g = 0, op[0] && (_ = 0)), _) try {
17
+ if (f = 1, y && (t = op[0] & 2 ? y["return"] : op[0] ? y["throw"] || ((t = y["return"]) && t.call(y), 0) : y.next) && !(t = t.call(y, op[1])).done) return t;
18
+ if (y = 0, t) op = [op[0] & 2, t.value];
19
+ switch (op[0]) {
20
+ case 0: case 1: t = op; break;
21
+ case 4: _.label++; return { value: op[1], done: false };
22
+ case 5: _.label++; y = op[1]; op = [0]; continue;
23
+ case 7: op = _.ops.pop(); _.trys.pop(); continue;
24
+ default:
25
+ if (!(t = _.trys, t = t.length > 0 && t[t.length - 1]) && (op[0] === 6 || op[0] === 2)) { _ = 0; continue; }
26
+ if (op[0] === 3 && (!t || (op[1] > t[0] && op[1] < t[3]))) { _.label = op[1]; break; }
27
+ if (op[0] === 6 && _.label < t[1]) { _.label = t[1]; t = op; break; }
28
+ if (t && _.label < t[2]) { _.label = t[2]; _.ops.push(op); break; }
29
+ if (t[2]) _.ops.pop();
30
+ _.trys.pop(); continue;
31
+ }
32
+ op = body.call(thisArg, _);
33
+ } catch (e) { op = [6, e]; y = 0; } finally { f = t = 0; }
34
+ if (op[0] & 5) throw op[1]; return { value: op[0] ? op[1] : void 0, done: true };
35
+ }
36
+ };
1
37
  var __values = (this && this.__values) || function(o) {
2
38
  var s = typeof Symbol === "function" && Symbol.iterator, m = s && o[s], i = 0;
3
39
  if (m) return m.call(o);
@@ -9,15 +45,51 @@ var __values = (this && this.__values) || function(o) {
9
45
  };
10
46
  throw new TypeError(s ? "Object is not iterable." : "Symbol.iterator is not defined.");
11
47
  };
12
- import { AcCmColor } from '@mlightcad/common';
48
+ import { AcCmColor, AcCmUiYieldGate, accmYieldToUi } from '@mlightcad/common';
13
49
  import { AcGeMatrix3d } from '@mlightcad/geometry-engine';
14
50
  import { AcDbBlockTableRecord } from '../database/AcDbBlockTableRecord';
51
+ /**
52
+ * Creates a zeroed top-level profile counter bag.
53
+ *
54
+ * @returns Fresh top-level stats object.
55
+ */
56
+ var emptyTopLevel = function () { return ({
57
+ hits: 0,
58
+ misses: 0,
59
+ hitMs: 0,
60
+ missBuildMs: 0,
61
+ missCompactMs: 0,
62
+ cloneMs: 0,
63
+ setCloneMs: 0,
64
+ applyMs: 0
65
+ }); };
66
+ /**
67
+ * Creates a zeroed {@link AcDbRenderingCacheProfileStats} instance.
68
+ *
69
+ * @returns Fresh profile stats with empty `blockMisses`.
70
+ */
71
+ var emptyProfileStats = function () { return ({
72
+ hits: 0,
73
+ misses: 0,
74
+ hitMs: 0,
75
+ missBuildMs: 0,
76
+ missCompactMs: 0,
77
+ cloneMs: 0,
78
+ setCloneMs: 0,
79
+ applyMs: 0,
80
+ topLevel: emptyTopLevel(),
81
+ blockMisses: []
82
+ }); };
15
83
  /**
16
84
  * Internal class used to cache rendered results to avoid duplicated rendering.
17
85
  *
18
86
  * This class can be used to improve performance when rendering block references.
19
- * Because different colors will result in different materials, the block name and
20
- * color are used together to create the cache key.
87
+ * Blocks without ByBlock-colored entities share one color-independent template.
88
+ * Blocks that contain ByBlock entities still key by block name and color because
89
+ * different INSERT colors produce different materials.
90
+ *
91
+ * Templates are compacted (same-material leaves merged) before caching so each
92
+ * INSERT clones O(material) geometries instead of O(entity) geometries.
21
93
  *
22
94
  * @internal
23
95
  *
@@ -41,6 +113,24 @@ var AcDbRenderingCache = /** @class */ (function () {
41
113
  function AcDbRenderingCache() {
42
114
  this._blocks = new Map();
43
115
  }
116
+ Object.defineProperty(AcDbRenderingCache, "profileStats", {
117
+ /**
118
+ * Accumulated profile counters. Only updated while {@link profiling} is true.
119
+ */
120
+ get: function () {
121
+ return this._profileStats;
122
+ },
123
+ enumerable: false,
124
+ configurable: true
125
+ });
126
+ /**
127
+ * Clears {@link profileStats} and draw nesting depth.
128
+ * Leaves {@link profiling} unchanged.
129
+ */
130
+ AcDbRenderingCache.resetProfile = function () {
131
+ this._profileStats = emptyProfileStats();
132
+ this._drawDepth = 0;
133
+ };
44
134
  Object.defineProperty(AcDbRenderingCache, "instance", {
45
135
  /**
46
136
  * Gets the singleton instance of the rendering cache.
@@ -64,6 +154,9 @@ var AcDbRenderingCache = /** @class */ (function () {
64
154
  /**
65
155
  * Creates a cache key by combining the block name and color.
66
156
  *
157
+ * Prefer {@link createCacheKey} when the block's ByBlock dependency is known,
158
+ * so color-independent blocks can share one template.
159
+ *
67
160
  * @param name - The block name
68
161
  * @param color - The resolved block color
69
162
  * @returns A unique key for the cache entry
@@ -82,9 +175,29 @@ var AcDbRenderingCache = /** @class */ (function () {
82
175
  }
83
176
  return "".concat(name, "_").concat(colorKey);
84
177
  };
178
+ /**
179
+ * Creates a cache key, omitting color when the block has no ByBlock entities.
180
+ *
181
+ * Color-independent keys let INSERTs that differ only by layer (ByLayer
182
+ * traits remapped at instance time) share one compacted template.
183
+ *
184
+ * @param name - The block name
185
+ * @param color - The resolved INSERT color (used only when `hasByBlockColor`)
186
+ * @param hasByBlockColor - Whether any entity in the block uses ByBlock color
187
+ * @returns Cache key: `name` alone, or `name_color` when ByBlock entities exist
188
+ */
189
+ AcDbRenderingCache.prototype.createCacheKey = function (name, color, hasByBlockColor) {
190
+ if (!hasByBlockColor) {
191
+ return name;
192
+ }
193
+ return this.createKey(name, color);
194
+ };
85
195
  /**
86
196
  * Stores rendering results of a block in the cache.
87
197
  *
198
+ * Deep-clones `group` so later mutations of the live instance cannot corrupt
199
+ * the cached template.
200
+ *
88
201
  * @param key - The key for the rendering results
89
202
  * @param group - The rendering results to store
90
203
  * @returns The stored rendering results (deep cloned)
@@ -95,15 +208,29 @@ var AcDbRenderingCache = /** @class */ (function () {
95
208
  * ```
96
209
  */
97
210
  AcDbRenderingCache.prototype.set = function (key, group) {
98
- group = group.fastDeepClone();
211
+ if (AcDbRenderingCache.profiling) {
212
+ var t0 = performance.now();
213
+ group = group.fastDeepClone();
214
+ var dt = performance.now() - t0;
215
+ AcDbRenderingCache._profileStats.setCloneMs += dt;
216
+ if (AcDbRenderingCache._drawDepth === 1) {
217
+ AcDbRenderingCache._profileStats.topLevel.setCloneMs += dt;
218
+ }
219
+ }
220
+ else {
221
+ group = group.fastDeepClone();
222
+ }
99
223
  this._blocks.set(key, group);
100
224
  return group;
101
225
  };
102
226
  /**
103
227
  * Gets rendering results with the specified key.
104
228
  *
229
+ * Returns a deep clone so callers can transform the instance without
230
+ * mutating the cached template.
231
+ *
105
232
  * @param name - The key of the rendering results
106
- * @returns The rendering results with the specified key, or undefined if not found
233
+ * @returns The cloned rendering results, or `undefined` if not found
107
234
  *
108
235
  * @example
109
236
  * ```typescript
@@ -116,7 +243,18 @@ var AcDbRenderingCache = /** @class */ (function () {
116
243
  AcDbRenderingCache.prototype.get = function (name) {
117
244
  var block = this._blocks.get(name);
118
245
  if (block) {
119
- block = block.fastDeepClone();
246
+ if (AcDbRenderingCache.profiling) {
247
+ var t0 = performance.now();
248
+ block = block.fastDeepClone();
249
+ var dt = performance.now() - t0;
250
+ AcDbRenderingCache._profileStats.cloneMs += dt;
251
+ if (AcDbRenderingCache._drawDepth === 1) {
252
+ AcDbRenderingCache._profileStats.topLevel.cloneMs += dt;
253
+ }
254
+ }
255
+ else {
256
+ block = block.fastDeepClone();
257
+ }
120
258
  }
121
259
  return block;
122
260
  };
@@ -137,7 +275,7 @@ var AcDbRenderingCache = /** @class */ (function () {
137
275
  return this._blocks.has(name);
138
276
  };
139
277
  /**
140
- * Clears all cached rendering results.
278
+ * Clears all cached rendering results and disposes owned geometry.
141
279
  *
142
280
  * @example
143
281
  * ```typescript
@@ -146,8 +284,95 @@ var AcDbRenderingCache = /** @class */ (function () {
146
284
  * ```
147
285
  */
148
286
  AcDbRenderingCache.prototype.clear = function () {
287
+ this._blocks.forEach(function (block) {
288
+ var _a;
289
+ (_a = block.dispose) === null || _a === void 0 ? void 0 : _a.call(block);
290
+ });
149
291
  this._blocks.clear();
150
292
  };
293
+ /**
294
+ * Prebuilds color-independent block templates before entity flush.
295
+ *
296
+ * Skips layout blocks (`*Model_Space` / `*Paper_Space*`), empty blocks,
297
+ * anonymous `*U` blocks, and blocks that contain ByBlock-colored entities
298
+ * (those require the INSERT color and are built on demand).
299
+ *
300
+ * @param renderer - Renderer used to convert block entities
301
+ * @param blocks - Iterator over block table records
302
+ * @param progress - Optional progress callback `(built, total, blockName)`
303
+ */
304
+ AcDbRenderingCache.prototype.prebuildAll = function (renderer, blocks, progress) {
305
+ return __awaiter(this, void 0, void 0, function () {
306
+ var candidates, blocks_1, blocks_1_1, block, total, built, prebuildColor, yieldGate, candidates_1, candidates_1_1, block, key, e_1_1;
307
+ var e_2, _a, e_1, _b;
308
+ return __generator(this, function (_c) {
309
+ switch (_c.label) {
310
+ case 0:
311
+ candidates = [];
312
+ try {
313
+ for (blocks_1 = __values(blocks), blocks_1_1 = blocks_1.next(); !blocks_1_1.done; blocks_1_1 = blocks_1.next()) {
314
+ block = blocks_1_1.value;
315
+ if (!block || !block.name) {
316
+ continue;
317
+ }
318
+ if (this.shouldSkipPrebuild(block)) {
319
+ continue;
320
+ }
321
+ candidates.push(block);
322
+ }
323
+ }
324
+ catch (e_2_1) { e_2 = { error: e_2_1 }; }
325
+ finally {
326
+ try {
327
+ if (blocks_1_1 && !blocks_1_1.done && (_a = blocks_1.return)) _a.call(blocks_1);
328
+ }
329
+ finally { if (e_2) throw e_2.error; }
330
+ }
331
+ total = candidates.length;
332
+ built = 0;
333
+ prebuildColor = new AcCmColor().setForeground();
334
+ yieldGate = new AcCmUiYieldGate();
335
+ _c.label = 1;
336
+ case 1:
337
+ _c.trys.push([1, 8, 9, 10]);
338
+ candidates_1 = __values(candidates), candidates_1_1 = candidates_1.next();
339
+ _c.label = 2;
340
+ case 2:
341
+ if (!!candidates_1_1.done) return [3 /*break*/, 7];
342
+ block = candidates_1_1.value;
343
+ key = this.createCacheKey(block.name, prebuildColor, false);
344
+ if (!this.has(key)) {
345
+ this.draw(renderer, block, prebuildColor, [], true);
346
+ }
347
+ built++;
348
+ if (!progress) return [3 /*break*/, 4];
349
+ return [4 /*yield*/, progress(built, total, block.name)];
350
+ case 3:
351
+ _c.sent();
352
+ _c.label = 4;
353
+ case 4: return [4 /*yield*/, yieldGate.maybeYield(accmYieldToUi)];
354
+ case 5:
355
+ _c.sent();
356
+ _c.label = 6;
357
+ case 6:
358
+ candidates_1_1 = candidates_1.next();
359
+ return [3 /*break*/, 2];
360
+ case 7: return [3 /*break*/, 10];
361
+ case 8:
362
+ e_1_1 = _c.sent();
363
+ e_1 = { error: e_1_1 };
364
+ return [3 /*break*/, 10];
365
+ case 9:
366
+ try {
367
+ if (candidates_1_1 && !candidates_1_1.done && (_b = candidates_1.return)) _b.call(candidates_1);
368
+ }
369
+ finally { if (e_1) throw e_1.error; }
370
+ return [7 /*endfinally*/];
371
+ case 10: return [2 /*return*/];
372
+ }
373
+ });
374
+ });
375
+ };
151
376
  /**
152
377
  * Draws a block table record and optionally caches the result.
153
378
  *
@@ -157,9 +382,11 @@ var AcDbRenderingCache = /** @class */ (function () {
157
382
  * @param renderer - The renderer to use for drawing
158
383
  * @param blockTableRecord - The block table record to draw
159
384
  * @param blockColor - The resolved color to use for rendering
385
+ * @param attributes - Attribute graphics to attach (WCS); converted to
386
+ * block-local space when `transform` is provided
160
387
  * @param cache - Whether to cache the rendering result (default: true)
161
- * @param transform - Optional transformation matrix to apply
162
- * @param normal - Optional normal vector
388
+ * @param transform - Optional block-reference transformation matrix
389
+ * @param normal - Optional extrusion / normal vector
163
390
  * @returns The rendered entity
164
391
  *
165
392
  * @example
@@ -168,6 +395,7 @@ var AcDbRenderingCache = /** @class */ (function () {
168
395
  * renderer,
169
396
  * blockRecord,
170
397
  * new AcCmColor().setRGBValue(0xFF0000),
398
+ * [],
171
399
  * true,
172
400
  * transform,
173
401
  * normal
@@ -175,89 +403,232 @@ var AcDbRenderingCache = /** @class */ (function () {
175
403
  * ```
176
404
  */
177
405
  AcDbRenderingCache.prototype.draw = function (renderer, blockTableRecord, blockColor, attributes, cache, transform, normal) {
178
- var e_1, _a;
406
+ var e_3, _a;
179
407
  var _b;
180
408
  if (attributes === void 0) { attributes = []; }
181
409
  if (cache === void 0) { cache = true; }
410
+ var profile = AcDbRenderingCache.profiling;
411
+ if (profile) {
412
+ AcDbRenderingCache._drawDepth++;
413
+ }
414
+ var isTop = profile && AcDbRenderingCache._drawDepth === 1;
415
+ var stats = AcDbRenderingCache._profileStats;
182
416
  var results = [];
183
- if (blockTableRecord != null) {
184
- var blockRgb = (_b = blockColor.RGB) !== null && _b !== void 0 ? _b : 0;
185
- var key = this.createKey(blockTableRecord.name, blockColor);
186
- var block_1;
187
- if (this.has(key)) {
188
- block_1 = this.get(key);
189
- }
190
- else {
191
- var entities = blockTableRecord.newIterator();
192
- try {
193
- for (var entities_1 = __values(entities), entities_1_1 = entities_1.next(); !entities_1_1.done; entities_1_1 = entities_1.next()) {
194
- var entity = entities_1_1.value;
195
- if (!entity.visibility) {
196
- continue;
417
+ try {
418
+ if (blockTableRecord != null) {
419
+ var blockRgb = (_b = blockColor.RGB) !== null && _b !== void 0 ? _b : 0;
420
+ var hasByBlockColor = this.blockHasByBlockColor(blockTableRecord);
421
+ var key = this.createCacheKey(blockTableRecord.name, blockColor, hasByBlockColor);
422
+ var block_1;
423
+ if (this.has(key)) {
424
+ var tHit0 = profile ? performance.now() : 0;
425
+ block_1 = this.get(key);
426
+ if (profile) {
427
+ var dt = performance.now() - tHit0;
428
+ stats.hits++;
429
+ stats.hitMs += dt;
430
+ if (isTop) {
431
+ stats.topLevel.hits++;
432
+ stats.topLevel.hitMs += dt;
197
433
  }
198
- // If the color of this entity is 'byBlock', then store the original color of this entity color
199
- // and set the color of this entity to block's color. After renderering this entity, restore
200
- // its original color
201
- if (entity.color.isByBlock) {
202
- _tmpColor.copy(entity.color);
203
- if (blockColor.isForeground) {
204
- entity.color.setForeground();
434
+ }
435
+ }
436
+ else {
437
+ var tBuild0 = profile ? performance.now() : 0;
438
+ var entities = blockTableRecord.newIterator();
439
+ try {
440
+ for (var entities_1 = __values(entities), entities_1_1 = entities_1.next(); !entities_1_1.done; entities_1_1 = entities_1.next()) {
441
+ var entity = entities_1_1.value;
442
+ if (!entity.visibility) {
443
+ continue;
444
+ }
445
+ // ByBlock entities temporarily inherit the INSERT color for material
446
+ // creation. Use a local saved color so nested draw() calls cannot
447
+ // corrupt a shared module-level scratch buffer.
448
+ if (entity.color.isByBlock) {
449
+ var savedColor = new AcCmColor().copy(entity.color);
450
+ try {
451
+ if (blockColor.isForeground) {
452
+ entity.color.setForeground();
453
+ }
454
+ else {
455
+ entity.color.setRGBValue(blockRgb);
456
+ }
457
+ this.addEntity(entity, results, renderer);
458
+ }
459
+ finally {
460
+ entity.color.copy(savedColor);
461
+ }
205
462
  }
206
463
  else {
207
- entity.color.setRGBValue(blockRgb);
464
+ this.addEntity(entity, results, renderer);
465
+ }
466
+ }
467
+ }
468
+ catch (e_3_1) { e_3 = { error: e_3_1 }; }
469
+ finally {
470
+ try {
471
+ if (entities_1_1 && !entities_1_1.done && (_a = entities_1.return)) _a.call(entities_1);
472
+ }
473
+ finally { if (e_3) throw e_3.error; }
474
+ }
475
+ block_1 = renderer.group(results);
476
+ var buildMs = 0;
477
+ if (profile) {
478
+ buildMs = performance.now() - tBuild0;
479
+ stats.missBuildMs += buildMs;
480
+ if (isTop) {
481
+ stats.topLevel.missBuildMs += buildMs;
482
+ }
483
+ }
484
+ // Merge same-material leaves before caching so INSERT clones are cheap.
485
+ var compactMs = 0;
486
+ if (block_1 === null || block_1 === void 0 ? void 0 : block_1.compactForInstancing) {
487
+ var tCompact0 = profile ? performance.now() : 0;
488
+ block_1.compactForInstancing();
489
+ if (profile) {
490
+ compactMs = performance.now() - tCompact0;
491
+ stats.missCompactMs += compactMs;
492
+ if (isTop) {
493
+ stats.topLevel.missCompactMs += compactMs;
208
494
  }
209
- this.addEntity(entity, results, renderer);
210
- entity.color.copy(_tmpColor);
211
495
  }
212
- else {
213
- this.addEntity(entity, results, renderer);
496
+ }
497
+ var setCloneBefore = profile ? stats.setCloneMs : 0;
498
+ if (block_1 && cache) {
499
+ // Transient anonymous blocks (*U…) are not reused across INSERTs.
500
+ if (blockTableRecord.name &&
501
+ !blockTableRecord.name.startsWith('*U')) {
502
+ this.set(key, block_1);
214
503
  }
215
504
  }
505
+ if (profile) {
506
+ stats.misses++;
507
+ if (isTop) {
508
+ stats.topLevel.misses++;
509
+ }
510
+ stats.blockMisses.push({
511
+ blockName: blockTableRecord.name || '(unnamed)',
512
+ buildMs: buildMs,
513
+ compactMs: compactMs,
514
+ setCloneMs: stats.setCloneMs - setCloneBefore
515
+ });
516
+ }
216
517
  }
217
- catch (e_1_1) { e_1 = { error: e_1_1 }; }
218
- finally {
219
- try {
220
- if (entities_1_1 && !entities_1_1.done && (_a = entities_1.return)) _a.call(entities_1);
518
+ var tApply0 = profile ? performance.now() : 0;
519
+ if (block_1 && transform) {
520
+ _tmpWorldTransform.copy(transform);
521
+ block_1.applyMatrix(_tmpWorldTransform);
522
+ if (normal && (normal.x != 0 || normal.y != 0 || normal.z != 1)) {
523
+ _tmpExtrusion.setFromExtrusionDirection(normal);
524
+ block_1.applyMatrix(_tmpExtrusion);
525
+ _tmpWorldTransform.premultiply(_tmpExtrusion);
221
526
  }
222
- finally { if (e_1) throw e_1.error; }
223
527
  }
224
- block_1 = renderer.group(results);
225
- if (block_1 && cache) {
226
- // If one block is one transient block whose name starts with '*U', don't cache it
227
- if (AcDbBlockTableRecord.name &&
228
- !AcDbBlockTableRecord.name.startsWith('*U')) {
229
- this.set(key, block_1);
528
+ if (block_1 && attributes && attributes.length > 0) {
529
+ // Attribute geometry is emitted in WCS. Convert it to block-local space so
530
+ // the block reference transform applied above places it correctly.
531
+ var inverse_1 = transform != null
532
+ ? _tmpInverse.copy(_tmpWorldTransform).invert()
533
+ : undefined;
534
+ attributes.forEach(function (attrib) {
535
+ if (inverse_1) {
536
+ attrib.applyMatrix(inverse_1);
537
+ }
538
+ block_1.addChild(attrib);
539
+ });
540
+ }
541
+ if (profile) {
542
+ var dt = performance.now() - tApply0;
543
+ stats.applyMs += dt;
544
+ if (isTop) {
545
+ stats.topLevel.applyMs += dt;
230
546
  }
231
547
  }
548
+ return block_1;
549
+ }
550
+ else {
551
+ return renderer.group(results);
232
552
  }
233
- if (block_1 && transform) {
234
- _tmpWorldTransform.copy(transform);
235
- block_1.applyMatrix(_tmpWorldTransform);
236
- if (normal && (normal.x != 0 || normal.y != 0 || normal.z != 1)) {
237
- _tmpExtrusion.setFromExtrusionDirection(normal);
238
- block_1.applyMatrix(_tmpExtrusion);
239
- _tmpWorldTransform.premultiply(_tmpExtrusion);
553
+ }
554
+ finally {
555
+ if (profile) {
556
+ AcDbRenderingCache._drawDepth--;
557
+ }
558
+ }
559
+ };
560
+ /**
561
+ * Returns whether `block` should be excluded from {@link prebuildAll}.
562
+ *
563
+ * Skips layout blocks, anonymous `*U` blocks, blocks with ByBlock colors
564
+ * (key depends on INSERT color), and blocks with no visible entities.
565
+ *
566
+ * @param block - Block table record to evaluate.
567
+ * @returns `true` when the block should not be prebuilt.
568
+ */
569
+ AcDbRenderingCache.prototype.shouldSkipPrebuild = function (block) {
570
+ var e_4, _a;
571
+ var name = block.name;
572
+ if (AcDbBlockTableRecord.isModelSapceName(name) ||
573
+ AcDbBlockTableRecord.isPaperSapceName(name)) {
574
+ return true;
575
+ }
576
+ if (name.startsWith('*U')) {
577
+ return true;
578
+ }
579
+ if (this.blockHasByBlockColor(block)) {
580
+ return true;
581
+ }
582
+ try {
583
+ // Empty blocks produce nothing useful to cache.
584
+ for (var _b = __values(block.newIterator()), _c = _b.next(); !_c.done; _c = _b.next()) {
585
+ var entity = _c.value;
586
+ if (entity.visibility) {
587
+ return false;
240
588
  }
241
589
  }
242
- if (block_1 && attributes && attributes.length > 0) {
243
- // Attribute geometry is emitted in WCS. Convert it to block-local space so
244
- // the block reference transform applied above places it correctly.
245
- var inverse_1 = transform != null
246
- ? _tmpInverse.copy(_tmpWorldTransform).invert()
247
- : undefined;
248
- attributes.forEach(function (attrib) {
249
- if (inverse_1) {
250
- attrib.applyMatrix(inverse_1);
251
- }
252
- block_1.addChild(attrib);
253
- });
590
+ }
591
+ catch (e_4_1) { e_4 = { error: e_4_1 }; }
592
+ finally {
593
+ try {
594
+ if (_c && !_c.done && (_a = _b.return)) _a.call(_b);
254
595
  }
255
- return block_1;
596
+ finally { if (e_4) throw e_4.error; }
256
597
  }
257
- else {
258
- return renderer.group(results);
598
+ return true;
599
+ };
600
+ /**
601
+ * Returns whether any visible entity in the block uses ByBlock color.
602
+ *
603
+ * @param blockTableRecord - Block whose entities are scanned.
604
+ * @returns `true` when at least one visible ByBlock-colored entity exists.
605
+ */
606
+ AcDbRenderingCache.prototype.blockHasByBlockColor = function (blockTableRecord) {
607
+ var e_5, _a;
608
+ try {
609
+ for (var _b = __values(blockTableRecord.newIterator()), _c = _b.next(); !_c.done; _c = _b.next()) {
610
+ var entity = _c.value;
611
+ if (entity.visibility && entity.color.isByBlock) {
612
+ return true;
613
+ }
614
+ }
615
+ }
616
+ catch (e_5_1) { e_5 = { error: e_5_1 }; }
617
+ finally {
618
+ try {
619
+ if (_c && !_c.done && (_a = _b.return)) _a.call(_b);
620
+ }
621
+ finally { if (e_5) throw e_5.error; }
259
622
  }
623
+ return false;
260
624
  };
625
+ /**
626
+ * Draws one visible entity and appends its graphic result to `results`.
627
+ *
628
+ * @param entity - Database entity to convert.
629
+ * @param results - Accumulator for graphic-interface entities.
630
+ * @param renderer - Renderer used for `worldDraw`.
631
+ */
261
632
  AcDbRenderingCache.prototype.addEntity = function (entity, results, renderer) {
262
633
  if (!entity.visibility) {
263
634
  return;
@@ -268,17 +639,36 @@ var AcDbRenderingCache = /** @class */ (function () {
268
639
  results.push(object);
269
640
  }
270
641
  };
642
+ /**
643
+ * Copies database identity/layer/visibility onto a graphic-interface entity.
644
+ *
645
+ * @param target - Graphic entity produced by `worldDraw`.
646
+ * @param source - Source database entity.
647
+ */
271
648
  AcDbRenderingCache.prototype.attachEntityInfo = function (target, source) {
272
649
  target.objectId = source.objectId;
273
650
  target.ownerId = source.ownerId;
274
651
  target.layerName = source.layer;
275
652
  target.visible = source.visibility;
276
653
  };
654
+ /**
655
+ * When true, {@link draw} / {@link get} / {@link set} accumulate
656
+ * {@link profileStats}. Off by default (zero overhead when false).
657
+ */
658
+ AcDbRenderingCache.profiling = false;
659
+ /**
660
+ * Mutable profile accumulator used while {@link profiling} is true.
661
+ */
662
+ AcDbRenderingCache._profileStats = emptyProfileStats();
663
+ /** Nesting depth of {@link draw} while profiling (1 = outermost). */
664
+ AcDbRenderingCache._drawDepth = 0;
277
665
  return AcDbRenderingCache;
278
666
  }());
279
667
  export { AcDbRenderingCache };
280
- var _tmpColor = /*@__PURE__*/ new AcCmColor();
668
+ /** Scratch matrix for the INSERT world transform applied in {@link AcDbRenderingCache.draw}. */
281
669
  var _tmpWorldTransform = /*@__PURE__*/ new AcGeMatrix3d();
670
+ /** Scratch matrix for extrusion/normal correction in {@link AcDbRenderingCache.draw}. */
282
671
  var _tmpExtrusion = /*@__PURE__*/ new AcGeMatrix3d();
672
+ /** Scratch inverse of the world transform used to bring ATTRIB geometry into block space. */
283
673
  var _tmpInverse = /*@__PURE__*/ new AcGeMatrix3d();
284
674
  //# sourceMappingURL=AcDbRenderingCache.js.map