@mlightcad/cad-simple-viewer 1.7.3 → 1.7.5

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 (235) hide show
  1. package/README.md +5 -0
  2. package/dist/cad-simple-viewer.js +10348 -8246
  3. package/dist/cad-simple-viewer.umd.cjs +431 -87
  4. package/dist/mtext-renderer-worker.js +2191 -2124
  5. package/lib/app/AcApDocManager.d.ts +57 -0
  6. package/lib/app/AcApDocManager.d.ts.map +1 -1
  7. package/lib/app/AcApDocManager.js +171 -9
  8. package/lib/app/AcApDocManager.js.map +1 -1
  9. package/lib/app/AcApOpenDatabaseOptions.d.ts +34 -8
  10. package/lib/app/AcApOpenDatabaseOptions.d.ts.map +1 -1
  11. package/lib/app/AcApOpenFileDialog.d.ts +1 -1
  12. package/lib/app/AcApOpenFileDialog.d.ts.map +1 -1
  13. package/lib/app/AcApOpenFileDialog.js +22 -92
  14. package/lib/app/AcApOpenFileDialog.js.map +1 -1
  15. package/lib/app/AcApOpenFileProfiler.d.ts +14 -0
  16. package/lib/app/AcApOpenFileProfiler.d.ts.map +1 -1
  17. package/lib/app/AcApOpenFileProfiler.js +25 -3
  18. package/lib/app/AcApOpenFileProfiler.js.map +1 -1
  19. package/lib/app/dataSource/AcApDataSource.d.ts +97 -0
  20. package/lib/app/dataSource/AcApDataSource.d.ts.map +1 -0
  21. package/lib/app/dataSource/AcApDataSource.js +2 -0
  22. package/lib/app/dataSource/AcApDataSource.js.map +1 -0
  23. package/lib/app/dataSource/AcApDataSourceManager.d.ts +70 -0
  24. package/lib/app/dataSource/AcApDataSourceManager.d.ts.map +1 -0
  25. package/lib/app/dataSource/AcApDataSourceManager.js +84 -0
  26. package/lib/app/dataSource/AcApDataSourceManager.js.map +1 -0
  27. package/lib/app/dataSource/AcApLocalDataSource.d.ts +25 -0
  28. package/lib/app/dataSource/AcApLocalDataSource.d.ts.map +1 -0
  29. package/lib/app/dataSource/AcApLocalDataSource.js +153 -0
  30. package/lib/app/dataSource/AcApLocalDataSource.js.map +1 -0
  31. package/lib/app/dataSource/AcApUrlDataSource.d.ts +17 -0
  32. package/lib/app/dataSource/AcApUrlDataSource.d.ts.map +1 -0
  33. package/lib/app/dataSource/AcApUrlDataSource.js +214 -0
  34. package/lib/app/dataSource/AcApUrlDataSource.js.map +1 -0
  35. package/lib/app/dataSource/acapBuildDataSourceMenu.d.ts +42 -0
  36. package/lib/app/dataSource/acapBuildDataSourceMenu.d.ts.map +1 -0
  37. package/lib/app/dataSource/acapBuildDataSourceMenu.js +121 -0
  38. package/lib/app/dataSource/acapBuildDataSourceMenu.js.map +1 -0
  39. package/lib/app/dataSource/acapInvokeDataSourceMenuAction.d.ts +17 -0
  40. package/lib/app/dataSource/acapInvokeDataSourceMenuAction.d.ts.map +1 -0
  41. package/lib/app/dataSource/acapInvokeDataSourceMenuAction.js +74 -0
  42. package/lib/app/dataSource/acapInvokeDataSourceMenuAction.js.map +1 -0
  43. package/lib/app/dataSource/acapOpenCenteredPopup.d.ts +13 -0
  44. package/lib/app/dataSource/acapOpenCenteredPopup.d.ts.map +1 -0
  45. package/lib/app/dataSource/acapOpenCenteredPopup.js +35 -0
  46. package/lib/app/dataSource/acapOpenCenteredPopup.js.map +1 -0
  47. package/lib/app/dataSource/acapOpenDataSourceResult.d.ts +13 -0
  48. package/lib/app/dataSource/acapOpenDataSourceResult.d.ts.map +1 -0
  49. package/lib/app/dataSource/acapOpenDataSourceResult.js +90 -0
  50. package/lib/app/dataSource/acapOpenDataSourceResult.js.map +1 -0
  51. package/lib/app/dataSource/acapRunDataSourceMenuAction.d.ts +15 -0
  52. package/lib/app/dataSource/acapRunDataSourceMenuAction.d.ts.map +1 -0
  53. package/lib/app/dataSource/acapRunDataSourceMenuAction.js +74 -0
  54. package/lib/app/dataSource/acapRunDataSourceMenuAction.js.map +1 -0
  55. package/lib/app/dataSource/acapWithDataSourceBusy.d.ts +12 -0
  56. package/lib/app/dataSource/acapWithDataSourceBusy.d.ts.map +1 -0
  57. package/lib/app/dataSource/acapWithDataSourceBusy.js +88 -0
  58. package/lib/app/dataSource/acapWithDataSourceBusy.js.map +1 -0
  59. package/lib/app/dataSource/index.d.ts +11 -0
  60. package/lib/app/dataSource/index.d.ts.map +1 -0
  61. package/lib/app/dataSource/index.js +10 -0
  62. package/lib/app/dataSource/index.js.map +1 -0
  63. package/lib/app/index.d.ts +1 -0
  64. package/lib/app/index.d.ts.map +1 -1
  65. package/lib/app/index.js +1 -0
  66. package/lib/app/index.js.map +1 -1
  67. package/lib/command/AcApZoomCmd.d.ts +3 -0
  68. package/lib/command/AcApZoomCmd.d.ts.map +1 -1
  69. package/lib/command/AcApZoomCmd.js +20 -6
  70. package/lib/command/AcApZoomCmd.js.map +1 -1
  71. package/lib/command/convert/AcApConvertToRasterImageCmd.d.ts +4 -2
  72. package/lib/command/convert/AcApConvertToRasterImageCmd.d.ts.map +1 -1
  73. package/lib/command/convert/AcApConvertToRasterImageCmd.js +33 -17
  74. package/lib/command/convert/AcApConvertToRasterImageCmd.js.map +1 -1
  75. package/lib/command/markup/AcApMarkupCalloutCmd.d.ts.map +1 -1
  76. package/lib/command/markup/AcApMarkupCalloutCmd.js +8 -4
  77. package/lib/command/markup/AcApMarkupCalloutCmd.js.map +1 -1
  78. package/lib/command/markup/AcApMarkupShapeCallout.d.ts.map +1 -1
  79. package/lib/command/markup/AcApMarkupShapeCallout.js +8 -4
  80. package/lib/command/markup/AcApMarkupShapeCallout.js.map +1 -1
  81. package/lib/command/markup/AcApMarkupUtil.d.ts.map +1 -1
  82. package/lib/command/markup/AcApMarkupUtil.js +6 -4
  83. package/lib/command/markup/AcApMarkupUtil.js.map +1 -1
  84. package/lib/command/measure/AcApMeasureAngleArc.d.ts +9 -2
  85. package/lib/command/measure/AcApMeasureAngleArc.d.ts.map +1 -1
  86. package/lib/command/measure/AcApMeasureAngleArc.js +9 -2
  87. package/lib/command/measure/AcApMeasureAngleArc.js.map +1 -1
  88. package/lib/command/measure/AcApMeasureAngleCmd.d.ts.map +1 -1
  89. package/lib/command/measure/AcApMeasureAngleCmd.js +17 -4
  90. package/lib/command/measure/AcApMeasureAngleCmd.js.map +1 -1
  91. package/lib/command/measure/AcApMeasureArcCmd.d.ts.map +1 -1
  92. package/lib/command/measure/AcApMeasureArcCmd.js +12 -8
  93. package/lib/command/measure/AcApMeasureArcCmd.js.map +1 -1
  94. package/lib/command/measure/AcApMeasureAreaCmd.d.ts.map +1 -1
  95. package/lib/command/measure/AcApMeasureAreaCmd.js +17 -4
  96. package/lib/command/measure/AcApMeasureAreaCmd.js.map +1 -1
  97. package/lib/command/measure/AcApMeasureContinuousCmd.d.ts.map +1 -1
  98. package/lib/command/measure/AcApMeasureContinuousCmd.js +36 -6
  99. package/lib/command/measure/AcApMeasureContinuousCmd.js.map +1 -1
  100. package/lib/command/measure/AcApMeasureDistanceCmd.d.ts.map +1 -1
  101. package/lib/command/measure/AcApMeasureDistanceCmd.js +28 -8
  102. package/lib/command/measure/AcApMeasureDistanceCmd.js.map +1 -1
  103. package/lib/command/measure/AcApMeasurementStore.d.ts.map +1 -1
  104. package/lib/command/measure/AcApMeasurementStore.js +44 -28
  105. package/lib/command/measure/AcApMeasurementStore.js.map +1 -1
  106. package/lib/command/measure/entity/AcApMeasureAngleEntity.d.ts.map +1 -1
  107. package/lib/command/measure/entity/AcApMeasureAngleEntity.js +43 -7
  108. package/lib/command/measure/entity/AcApMeasureAngleEntity.js.map +1 -1
  109. package/lib/command/measure/entity/AcApMeasureArcEntity.d.ts.map +1 -1
  110. package/lib/command/measure/entity/AcApMeasureArcEntity.js +46 -8
  111. package/lib/command/measure/entity/AcApMeasureArcEntity.js.map +1 -1
  112. package/lib/command/measure/entity/AcApMeasureAreaEntity.d.ts.map +1 -1
  113. package/lib/command/measure/entity/AcApMeasureAreaEntity.js +43 -7
  114. package/lib/command/measure/entity/AcApMeasureAreaEntity.js.map +1 -1
  115. package/lib/command/measure/entity/AcApMeasureDistanceEntity.d.ts.map +1 -1
  116. package/lib/command/measure/entity/AcApMeasureDistanceEntity.js +56 -8
  117. package/lib/command/measure/entity/AcApMeasureDistanceEntity.js.map +1 -1
  118. package/lib/command/measure/entity/AcApMeasureEntity.d.ts +8 -0
  119. package/lib/command/measure/entity/AcApMeasureEntity.d.ts.map +1 -1
  120. package/lib/command/measure/entity/AcApMeasureEntity.js +16 -1
  121. package/lib/command/measure/entity/AcApMeasureEntity.js.map +1 -1
  122. package/lib/command/measure/entity/AcApMeasureEntityGrips.d.ts.map +1 -1
  123. package/lib/command/measure/entity/AcApMeasureEntityGrips.js +2 -1
  124. package/lib/command/measure/entity/AcApMeasureEntityGrips.js.map +1 -1
  125. package/lib/command/overlay/AcApHtmlLivePreview.d.ts +6 -0
  126. package/lib/command/overlay/AcApHtmlLivePreview.d.ts.map +1 -1
  127. package/lib/command/overlay/AcApHtmlLivePreview.js +9 -2
  128. package/lib/command/overlay/AcApHtmlLivePreview.js.map +1 -1
  129. package/lib/command/overlay/AcApOverlayDrawUtil.d.ts +5 -0
  130. package/lib/command/overlay/AcApOverlayDrawUtil.d.ts.map +1 -1
  131. package/lib/command/overlay/AcApOverlayDrawUtil.js +54 -23
  132. package/lib/command/overlay/AcApOverlayDrawUtil.js.map +1 -1
  133. package/lib/editor/global/AcEdConditionWaiter.d.ts +3 -0
  134. package/lib/editor/global/AcEdConditionWaiter.d.ts.map +1 -1
  135. package/lib/editor/global/AcEdConditionWaiter.js +9 -2
  136. package/lib/editor/global/AcEdConditionWaiter.js.map +1 -1
  137. package/lib/editor/global/AcEdUiTheme.d.ts +10 -1
  138. package/lib/editor/global/AcEdUiTheme.d.ts.map +1 -1
  139. package/lib/editor/global/AcEdUiTheme.js +35 -2
  140. package/lib/editor/global/AcEdUiTheme.js.map +1 -1
  141. package/lib/editor/input/ui/AcEdCommandLine.d.ts.map +1 -1
  142. package/lib/editor/input/ui/AcEdCommandLine.js +7 -7
  143. package/lib/editor/input/ui/AcEdCommandLine.js.map +1 -1
  144. package/lib/editor/view/AcEdBaseView.d.ts +14 -1
  145. package/lib/editor/view/AcEdBaseView.d.ts.map +1 -1
  146. package/lib/editor/view/AcEdBaseView.js.map +1 -1
  147. package/lib/i18n/ar/main.d.ts +28 -0
  148. package/lib/i18n/ar/main.d.ts.map +1 -1
  149. package/lib/i18n/ar/main.js +28 -0
  150. package/lib/i18n/ar/main.js.map +1 -1
  151. package/lib/i18n/cs/main.d.ts +28 -0
  152. package/lib/i18n/cs/main.d.ts.map +1 -1
  153. package/lib/i18n/cs/main.js +28 -0
  154. package/lib/i18n/cs/main.js.map +1 -1
  155. package/lib/i18n/en/main.d.ts +28 -0
  156. package/lib/i18n/en/main.d.ts.map +1 -1
  157. package/lib/i18n/en/main.js +28 -0
  158. package/lib/i18n/en/main.js.map +1 -1
  159. package/lib/i18n/tr/main.d.ts +28 -0
  160. package/lib/i18n/tr/main.d.ts.map +1 -1
  161. package/lib/i18n/tr/main.js +28 -0
  162. package/lib/i18n/tr/main.js.map +1 -1
  163. package/lib/i18n/zh/main.d.ts +28 -0
  164. package/lib/i18n/zh/main.d.ts.map +1 -1
  165. package/lib/i18n/zh/main.js +28 -0
  166. package/lib/i18n/zh/main.js.map +1 -1
  167. package/lib/spatialIndex/AcTrHierarchicalSpatialIndex.d.ts +11 -0
  168. package/lib/spatialIndex/AcTrHierarchicalSpatialIndex.d.ts.map +1 -1
  169. package/lib/spatialIndex/AcTrHierarchicalSpatialIndex.js +92 -0
  170. package/lib/spatialIndex/AcTrHierarchicalSpatialIndex.js.map +1 -1
  171. package/lib/ui/AcUiFileOpenPanel.d.ts +156 -0
  172. package/lib/ui/AcUiFileOpenPanel.d.ts.map +1 -0
  173. package/lib/ui/AcUiFileOpenPanel.js +695 -0
  174. package/lib/ui/AcUiFileOpenPanel.js.map +1 -0
  175. package/lib/ui/icons.d.ts +4 -0
  176. package/lib/ui/icons.d.ts.map +1 -1
  177. package/lib/ui/icons.js +4 -0
  178. package/lib/ui/icons.js.map +1 -1
  179. package/lib/ui/index.d.ts +1 -0
  180. package/lib/ui/index.d.ts.map +1 -1
  181. package/lib/ui/index.js +1 -0
  182. package/lib/ui/index.js.map +1 -1
  183. package/lib/util/AcApDrawingExtents.d.ts +29 -0
  184. package/lib/util/AcApDrawingExtents.d.ts.map +1 -0
  185. package/lib/util/AcApDrawingExtents.js +34 -0
  186. package/lib/util/AcApDrawingExtents.js.map +1 -0
  187. package/lib/util/AcApFontUtil.d.ts +18 -0
  188. package/lib/util/AcApFontUtil.d.ts.map +1 -1
  189. package/lib/util/AcApFontUtil.js +126 -0
  190. package/lib/util/AcApFontUtil.js.map +1 -1
  191. package/lib/util/AcApMeasureBadgeFont.d.ts +99 -0
  192. package/lib/util/AcApMeasureBadgeFont.d.ts.map +1 -0
  193. package/lib/util/AcApMeasureBadgeFont.js +207 -0
  194. package/lib/util/AcApMeasureBadgeFont.js.map +1 -0
  195. package/lib/util/AcApMeasurementUnits.d.ts.map +1 -1
  196. package/lib/util/AcApMeasurementUnits.js +41 -2
  197. package/lib/util/AcApMeasurementUnits.js.map +1 -1
  198. package/lib/util/AcApTextStyleFontPreload.d.ts +42 -0
  199. package/lib/util/AcApTextStyleFontPreload.d.ts.map +1 -0
  200. package/lib/util/AcApTextStyleFontPreload.js +149 -0
  201. package/lib/util/AcApTextStyleFontPreload.js.map +1 -0
  202. package/lib/util/index.d.ts +3 -0
  203. package/lib/util/index.d.ts.map +1 -1
  204. package/lib/util/index.js +3 -0
  205. package/lib/util/index.js.map +1 -1
  206. package/lib/view/AcTrExtentCluster.d.ts +10 -0
  207. package/lib/view/AcTrExtentCluster.d.ts.map +1 -1
  208. package/lib/view/AcTrExtentCluster.js +76 -0
  209. package/lib/view/AcTrExtentCluster.js.map +1 -1
  210. package/lib/view/AcTrIntelligentExtents.d.ts +8 -0
  211. package/lib/view/AcTrIntelligentExtents.d.ts.map +1 -1
  212. package/lib/view/AcTrIntelligentExtents.js +247 -10
  213. package/lib/view/AcTrIntelligentExtents.js.map +1 -1
  214. package/lib/view/AcTrLayer.d.ts +4 -0
  215. package/lib/view/AcTrLayer.d.ts.map +1 -1
  216. package/lib/view/AcTrLayer.js +6 -0
  217. package/lib/view/AcTrLayer.js.map +1 -1
  218. package/lib/view/AcTrLayout.d.ts +41 -0
  219. package/lib/view/AcTrLayout.d.ts.map +1 -1
  220. package/lib/view/AcTrLayout.js +132 -0
  221. package/lib/view/AcTrLayout.js.map +1 -1
  222. package/lib/view/AcTrScene.d.ts +11 -0
  223. package/lib/view/AcTrScene.d.ts.map +1 -1
  224. package/lib/view/AcTrScene.js +84 -48
  225. package/lib/view/AcTrScene.js.map +1 -1
  226. package/lib/view/AcTrView2d.d.ts +79 -6
  227. package/lib/view/AcTrView2d.d.ts.map +1 -1
  228. package/lib/view/AcTrView2d.js +411 -113
  229. package/lib/view/AcTrView2d.js.map +1 -1
  230. package/lib/view/AcTrWorkSlice.d.ts +23 -0
  231. package/lib/view/AcTrWorkSlice.d.ts.map +1 -0
  232. package/lib/view/AcTrWorkSlice.js +92 -0
  233. package/lib/view/AcTrWorkSlice.js.map +1 -0
  234. package/package.json +8 -8
  235. package/src/ui/icons.ts +9 -0
@@ -96,10 +96,10 @@ var __spreadArray = (this && this.__spreadArray) || function (to, from, pack) {
96
96
  }
97
97
  return to.concat(ar || Array.prototype.slice.call(from));
98
98
  };
99
- import { AcCmUiYieldGate, AcDbAttribute, AcDbBlockReference, acdbHostApplicationServices, AcDbMText, AcDbRasterImage, AcDbRay, AcDbSysVarManager, AcDbViewport, AcDbXline, AcGeBox2d, AcGePoint2d, acgiForegroundColorForBackground, log } from '@mlightcad/data-model';
99
+ import { AcCmUiYieldGate, AcDbAttribute, AcDbBlockReference, acdbHostApplicationServices, AcDbMText, AcDbRasterImage, AcDbRay, AcDbRenderingCache, AcDbSysVarManager, AcDbViewport, AcDbXline, AcGeBox2d, AcGePoint2d, acgiForegroundColorForBackground, log } from '@mlightcad/data-model';
100
100
  import { AcDbSystemVariables } from '@mlightcad/data-model';
101
101
  import { FontManager } from '@mlightcad/mtext-renderer';
102
- import { AcTrEntity, AcTrGlyphEntity, AcTrGroup, AcTrMTextRenderer, AcTrRenderer, AcTrViewportView, hasPendingComplexLineTypeGlyphs } from '@mlightcad/three-renderer';
102
+ import { AcTrEntity, AcTrGlyphEntity, AcTrGroup, AcTrMTextRenderer, AcTrRenderer, AcTrViewportView, hasPendingComplexLineTypeGlyphs, setAcTrDrawOrderZAllocator } from '@mlightcad/three-renderer';
103
103
  import { AcTrMatrixUtil } from '@mlightcad/three-renderer';
104
104
  import * as THREE from 'three';
105
105
  import Stats from 'three/examples/jsm/libs/stats.module';
@@ -115,6 +115,7 @@ import { acedEntityIntersectsSelectionBox, acedNeedsCrossingGeometryRefine } fro
115
115
  import { isEffectiveSpatialQueryHit } from '../editor/view/AcEdSpatialQueryResult';
116
116
  import { AcTrGeometryUtil } from '../util';
117
117
  import { acapRunDatabaseEdit } from '../util/AcApDatabaseEdit';
118
+ import { collectTextStyleFontNames, planTextStyleFontPreload } from '../util/AcApTextStyleFontPreload';
118
119
  import { ACAP_READING_MODE_BACKGROUND, AcApReadingModeState } from './AcApReadingMode';
119
120
  import { trySelectReviewOverlay, trySelectReviewOverlaysByBox } from './AcEdReviewOverlayPick';
120
121
  import { AcEdViewKeyHandler } from './AcEdViewKeyHandler';
@@ -122,7 +123,7 @@ import { shouldExtendBboxForDirectEntity, tryBuildDirectEntityMeta } from './AcT
122
123
  import { AcTrEntityDisplayController } from './AcTrEntityDisplayController';
123
124
  import { assertAcTrGroupWcsBboxesConsistent, unionGroupWcsChildBoxes } from './AcTrGroupWcsBboxAssert';
124
125
  import { AcTrInheritedLayerMaterialMapper } from './AcTrInheritedLayerMaterialMapper';
125
- import { computeIntelligentExtents } from './AcTrIntelligentExtents';
126
+ import { computeIntelligentExtentsAsync } from './AcTrIntelligentExtents';
126
127
  import { AcTrLayer } from './AcTrLayer';
127
128
  import { AcTrLayerAppearanceController } from './AcTrLayerAppearanceController';
128
129
  import { AcTrLayout } from './AcTrLayout';
@@ -131,6 +132,7 @@ import { AcTrLayoutViewManager } from './AcTrLayoutViewManager';
131
132
  import { sortPickResults } from './AcTrPickResultUtil';
132
133
  import { AcTrProgressiveOpenFitController } from './AcTrProgressiveOpenFitController';
133
134
  import { AcTrScene } from './AcTrScene';
135
+ import { AcTrWorkSlice } from './AcTrWorkSlice';
134
136
  import { shouldRegenDatabaseAfterFontLoad } from './fontLoadRegen';
135
137
  /**
136
138
  * Default view option values
@@ -269,6 +271,16 @@ var AcTrView2d = /** @class */ (function (_super) {
269
271
  * geometry paints incrementally while the open overlay is still visible.
270
272
  */
271
273
  _this._progressiveRendering = false;
274
+ /**
275
+ * When true, open-time convert includes off/frozen-layer entities so HTML
276
+ * export does not need a second convert pass for those entities.
277
+ */
278
+ _this._convertInvisibleLayers = false;
279
+ /**
280
+ * When false, {@link batchConvert} skips cooperative setTimeout yields.
281
+ * Headless CLI sets this false; interactive viewers leave it true.
282
+ */
283
+ _this._cooperativeYield = true;
272
284
  /**
273
285
  * Serial convert queue for progressive opens. Chunks from `entityAppended`
274
286
  * enqueue here and a single drain loop runs {@link batchConvert}, so scene
@@ -341,6 +353,21 @@ var AcTrView2d = /** @class */ (function (_super) {
341
353
  _this._isDirty = true;
342
354
  }
343
355
  });
356
+ /**
357
+ * Promise that resolves when text-style fonts needed by deferred glyph jobs
358
+ * are ready. Shared so concurrent deferred jobs do not each await a long
359
+ * font preload.
360
+ */
361
+ _this._deferredFontsReady = null;
362
+ /** Convert-phase wall timers (ms) for OPENPERF diagnostics. */
363
+ _this._convertPhaseMs = {
364
+ finishGeometry: 0,
365
+ handleGroup: 0,
366
+ addEntity: 0,
367
+ awaitFonts: 0
368
+ };
369
+ /** Last text-style font preload plan (for OPENPERF). */
370
+ _this._fontPreloadDiag = null;
344
371
  _this.animate = function () {
345
372
  var _a;
346
373
  _this._rafId = requestAnimationFrame(_this.animate);
@@ -385,6 +412,9 @@ var AcTrView2d = /** @class */ (function (_super) {
385
412
  renderer.setPixelRatio(Math.min(window.devicePixelRatio, 2));
386
413
  renderer.setSize(_this.width, _this.height);
387
414
  _this._renderer = new AcTrRenderer(renderer);
415
+ // Shared across all layer batched groups so later entities (e.g. wipeouts)
416
+ // occlude earlier linework via depth, matching AutoCAD draw order.
417
+ setAcTrDrawOrderZAllocator(function () { return _this._renderer.allocateDrawOrderZ(); });
388
418
  var fontMapping = AcApSettingManager.instance.fontMapping;
389
419
  _this._renderer.setFontMapping(fontMapping);
390
420
  _this._renderer.events.fontNotFound.addEventListener(function (args) {
@@ -691,6 +721,59 @@ var AcTrView2d = /** @class */ (function (_super) {
691
721
  _this.resetDeferredGeometryQueue();
692
722
  return _this;
693
723
  }
724
+ AcTrView2d.prototype.ensureDeferredFontsReady = function () {
725
+ var _this = this;
726
+ if (!this._deferredFontsReady) {
727
+ var t0_1 = performance.now();
728
+ // Preset (fallback) + STYLE-table faces must both be ready before glyph
729
+ // bake. Linework convert does not await this promise.
730
+ var ready = Promise.all([
731
+ this.awaitPresetFontsReadySafe(),
732
+ this.awaitTextStyleFontsReady()
733
+ ]).then(function () { return undefined; }, function () { return undefined; });
734
+ this._deferredFontsReady = ready.then(function () {
735
+ _this._convertPhaseMs.awaitFonts += performance.now() - t0_1;
736
+ });
737
+ }
738
+ return this._deferredFontsReady;
739
+ };
740
+ /**
741
+ * Awaits DocManager preset preload when the singleton exists.
742
+ * No-op in unit tests that construct a view without a manager.
743
+ */
744
+ AcTrView2d.prototype.awaitPresetFontsReadySafe = function () {
745
+ return __awaiter(this, void 0, void 0, function () {
746
+ var singleton;
747
+ return __generator(this, function (_a) {
748
+ switch (_a.label) {
749
+ case 0:
750
+ singleton = AcApDocManager;
751
+ if (!singleton._instance) {
752
+ return [2 /*return*/];
753
+ }
754
+ return [4 /*yield*/, singleton._instance.awaitPresetFontsReady()];
755
+ case 1:
756
+ _a.sent();
757
+ return [2 /*return*/];
758
+ }
759
+ });
760
+ });
761
+ };
762
+ /**
763
+ * Returns and resets convert-phase wall timers collected during the last open.
764
+ */
765
+ AcTrView2d.prototype.takeConvertPhaseTimings = function () {
766
+ var snapshot = __assign(__assign({}, this._convertPhaseMs), { fontPreload: this._fontPreloadDiag
767
+ ? __assign({}, this._fontPreloadDiag) : undefined });
768
+ this._convertPhaseMs = {
769
+ finishGeometry: 0,
770
+ handleGroup: 0,
771
+ addEntity: 0,
772
+ awaitFonts: 0
773
+ };
774
+ this._fontPreloadDiag = null;
775
+ return snapshot;
776
+ };
694
777
  AcTrView2d.prototype.getPointerSelectionAction = function (e) {
695
778
  return resolvePointerSelectionAction(e);
696
779
  };
@@ -906,6 +989,32 @@ var AcTrView2d = /** @class */ (function (_super) {
906
989
  enumerable: false,
907
990
  configurable: true
908
991
  });
992
+ Object.defineProperty(AcTrView2d.prototype, "convertInvisibleLayers", {
993
+ /**
994
+ * When true, open-time convert includes off/frozen-layer entities.
995
+ */
996
+ get: function () {
997
+ return this._convertInvisibleLayers;
998
+ },
999
+ set: function (value) {
1000
+ this._convertInvisibleLayers = value;
1001
+ },
1002
+ enumerable: false,
1003
+ configurable: true
1004
+ });
1005
+ Object.defineProperty(AcTrView2d.prototype, "cooperativeYield", {
1006
+ /**
1007
+ * When false, entity convert skips cooperative yields (headless export).
1008
+ */
1009
+ get: function () {
1010
+ return this._cooperativeYield;
1011
+ },
1012
+ set: function (value) {
1013
+ this._cooperativeYield = value;
1014
+ },
1015
+ enumerable: false,
1016
+ configurable: true
1017
+ });
909
1018
  Object.defineProperty(AcTrView2d.prototype, "progressiveOpenStats", {
910
1019
  /**
911
1020
  * Open-convert counters for OPENPROF / palette (cooperative yields during
@@ -1042,6 +1151,9 @@ var AcTrView2d = /** @class */ (function (_super) {
1042
1151
  // Style-manager changeForeground only updates cache entries; batch
1043
1152
  // containers own private material clones and must be repainted too.
1044
1153
  this._scene.repaintForegroundMaterials(acgiForegroundColorForBackground(value));
1154
+ // Wipeouts track the canvas background (isBackgroundFill); repaint their
1155
+ // batch-owned clones the same way as ACI-7 foreground materials.
1156
+ this._scene.repaintBackgroundMaterials(value);
1045
1157
  this.resyncForegroundLayersForBackground();
1046
1158
  if (this._readingMode.isEnabled) {
1047
1159
  this._readingMode.noteLayoutBackground(value);
@@ -1561,7 +1673,7 @@ var AcTrView2d = /** @class */ (function (_super) {
1561
1673
  _this.endProgressiveOpenFit();
1562
1674
  return;
1563
1675
  }
1564
- _this._progressiveOpenFit.applyFinalFit(function () { return _this.resolveLayoutFitBox(); });
1676
+ _this._progressiveOpenFit.applyFinalFit(function () { return _this.getDrawingExtents(); });
1565
1677
  _this.endProgressiveOpenFit();
1566
1678
  var originalBtrId = layoutBtrId !== null && layoutBtrId !== void 0 ? layoutBtrId : _this.activeLayoutBtrId;
1567
1679
  if (originalBtrId) {
@@ -1593,27 +1705,87 @@ var AcTrView2d = /** @class */ (function (_super) {
1593
1705
  AcTrView2d.prototype.zoomToSmartExtents = function (timeout) {
1594
1706
  var _this = this;
1595
1707
  if (timeout === void 0) { timeout = 0; }
1596
- var waiter = new AcEdConditionWaiter(function () { return !_this.isProcessingEntities; }, function () {
1597
- var smart = _this.resolveSmartFitBox();
1598
- if (smart) {
1599
- _this.zoomTo(smart);
1600
- _this._isDirty = true;
1601
- _this.endProgressiveOpenFit();
1602
- return;
1603
- }
1604
- _this._progressiveOpenFit.applyFinalFit(function () { return _this.resolveLayoutFitBox(); });
1605
- _this.endProgressiveOpenFit();
1606
- }, 300, timeout);
1607
- waiter.start();
1708
+ return new Promise(function (resolve, reject) {
1709
+ var waiter = new AcEdConditionWaiter(function () { return !_this.isProcessingEntities; }, function () {
1710
+ void (function () { return __awaiter(_this, void 0, void 0, function () {
1711
+ var smart, error_2;
1712
+ var _this = this;
1713
+ return __generator(this, function (_a) {
1714
+ switch (_a.label) {
1715
+ case 0:
1716
+ _a.trys.push([0, 2, , 3]);
1717
+ return [4 /*yield*/, this.resolveSmartFitBox()];
1718
+ case 1:
1719
+ smart = _a.sent();
1720
+ if (smart) {
1721
+ this.zoomTo(smart);
1722
+ this._isDirty = true;
1723
+ this.endProgressiveOpenFit();
1724
+ resolve();
1725
+ return [2 /*return*/];
1726
+ }
1727
+ this._progressiveOpenFit.applyFinalFit(function () {
1728
+ return _this.getDrawingExtents();
1729
+ });
1730
+ this.endProgressiveOpenFit();
1731
+ resolve();
1732
+ return [3 /*break*/, 3];
1733
+ case 2:
1734
+ error_2 = _a.sent();
1735
+ // Always clear progressive-open framing so a failed smart fit
1736
+ // cannot leave the open-fit overlay/state stuck indefinitely.
1737
+ this.endProgressiveOpenFit();
1738
+ reject(error_2);
1739
+ return [3 /*break*/, 3];
1740
+ case 3: return [2 /*return*/];
1741
+ }
1742
+ });
1743
+ }); })();
1744
+ }, 300, timeout);
1745
+ waiter.start();
1746
+ });
1608
1747
  };
1609
1748
  /**
1610
1749
  * Resolves intelligent zoom extents from spatial-index entity boxes.
1750
+ * Reuses the layout cache until entity geometry extents are invalidated.
1751
+ * Collects and clusters cooperatively so the UI thread stays responsive.
1611
1752
  */
1612
1753
  AcTrView2d.prototype.resolveSmartFitBox = function () {
1613
- var activeLayout = this._scene.activeLayout;
1614
- if (!activeLayout)
1615
- return undefined;
1616
- return computeIntelligentExtents(activeLayout.collectSpatialExtentBoxes());
1754
+ return __awaiter(this, void 0, void 0, function () {
1755
+ var activeLayout, cached, generation, work, entries, smart;
1756
+ return __generator(this, function (_a) {
1757
+ switch (_a.label) {
1758
+ case 0:
1759
+ activeLayout = this._scene.activeLayout;
1760
+ if (!activeLayout)
1761
+ return [2 /*return*/, undefined];
1762
+ cached = activeLayout.cachedSmartExtents;
1763
+ if (cached) {
1764
+ return [2 /*return*/, cached];
1765
+ }
1766
+ generation = activeLayout.smartExtentsGeneration;
1767
+ work = new AcTrWorkSlice();
1768
+ return [4 /*yield*/, activeLayout.collectSpatialExtentBoxesAsync(work)];
1769
+ case 1:
1770
+ entries = _a.sent();
1771
+ return [4 /*yield*/, computeIntelligentExtentsAsync(entries, work)
1772
+ // Geometry changed while we yielded: discard this result (a newer cache
1773
+ // may already exist; otherwise the caller falls back to drawing extents).
1774
+ ];
1775
+ case 2:
1776
+ smart = _a.sent();
1777
+ // Geometry changed while we yielded: discard this result (a newer cache
1778
+ // may already exist; otherwise the caller falls back to drawing extents).
1779
+ if (activeLayout.smartExtentsGeneration !== generation) {
1780
+ return [2 /*return*/, activeLayout.cachedSmartExtents];
1781
+ }
1782
+ if (smart) {
1783
+ activeLayout.cachedSmartExtents = smart;
1784
+ }
1785
+ return [2 /*return*/, smart];
1786
+ }
1787
+ });
1788
+ });
1617
1789
  };
1618
1790
  /**
1619
1791
  * @inheritdoc
@@ -1667,7 +1839,9 @@ var AcTrView2d = /** @class */ (function (_super) {
1667
1839
  return entity;
1668
1840
  return undefined;
1669
1841
  }
1670
- if (entity instanceof AcDbAttribute) {
1842
+ if (entity instanceof AcDbAttribute ||
1843
+ entity.type === 'Attrib' ||
1844
+ entity.type === 'Attribute') {
1671
1845
  var owner = AcApDocManager.instance.curDocument.database.tables.blockTable.getEntityById(entity.ownerId);
1672
1846
  if (owner instanceof AcDbBlockReference &&
1673
1847
  owner.attributeIterator().count > 0) {
@@ -2344,10 +2518,14 @@ var AcTrView2d = /** @class */ (function (_super) {
2344
2518
  this._externallyFramedLayouts.add(layoutBtrId);
2345
2519
  };
2346
2520
  /**
2347
- * Resolves the 2D box to frame for the active layout once entities are
2348
- * converted. Uses {@link AcTrScene.box}, which is derived from batch geometry.
2521
+ * Returns the 2D box of drawable geometry in the active layout.
2522
+ *
2523
+ * Uses {@link AcTrScene.box}, which is derived from batch geometry — not
2524
+ * database header `EXTMIN`/`EXTMAX`, which are often stale on real DWGs.
2525
+ *
2526
+ * @inheritdoc
2349
2527
  */
2350
- AcTrView2d.prototype.resolveLayoutFitBox = function () {
2528
+ AcTrView2d.prototype.getDrawingExtents = function () {
2351
2529
  var sceneBox = this._scene.box;
2352
2530
  if (sceneBox && !sceneBox.isEmpty()) {
2353
2531
  return AcTrGeometryUtil.threeBox3dToGeBox2d(sceneBox);
@@ -2375,7 +2553,7 @@ var AcTrView2d = /** @class */ (function (_super) {
2375
2553
  * populated. Many parsers leave this empty (we've seen `(0,0)-(0,0)`),
2376
2554
  * so it sits below the viewport-based heuristic.
2377
2555
  *
2378
- * 4. **`resolveLayoutFitBox`** (entity extents from batch geometry) —
2556
+ * 4. **`getDrawingExtents`** (entity extents from batch geometry) —
2379
2557
  * last-resort fallback for layouts with no viewports and no
2380
2558
  * sensible limits/extents (e.g. a freshly created empty paper).
2381
2559
  * Vulnerable to scale-mismatch outliers, but better than no zoom.
@@ -2421,7 +2599,7 @@ var AcTrView2d = /** @class */ (function (_super) {
2421
2599
  _this.zoomTo(new AcGeBox2d({ x: extents.min.x, y: extents.min.y }, { x: extents.max.x, y: extents.max.y }));
2422
2600
  }
2423
2601
  else {
2424
- var box = _this.resolveLayoutFitBox();
2602
+ var box = _this.getDrawingExtents();
2425
2603
  if (box) {
2426
2604
  _this.zoomTo(box);
2427
2605
  }
@@ -2447,12 +2625,15 @@ var AcTrView2d = /** @class */ (function (_super) {
2447
2625
  this.resetDeferredGeometryQueue();
2448
2626
  this._entityProcessingIdleAt = 0;
2449
2627
  this._scene.clear();
2628
+ this._renderer.resetDrawOrderZ();
2450
2629
  this._isDirty = true;
2451
2630
  this._missedImages.clear();
2452
2631
  this._initializedLayouts.clear();
2453
2632
  this._externallyFramedLayouts.clear();
2454
2633
  this._loadingLayouts.clear();
2455
2634
  this._renderer.dispose();
2635
+ // Drop block templates when the scene is torn down (next open / close).
2636
+ AcDbRenderingCache.instance.clear();
2456
2637
  eventBus.emit('missed-data-changed', {});
2457
2638
  };
2458
2639
  /**
@@ -2995,44 +3176,71 @@ var AcTrView2d = /** @class */ (function (_super) {
2995
3176
  *
2996
3177
  * Call when conversion stage `STYLE` ends so the download overlaps later
2997
3178
  * parse stages and linework convert. Does not block the caller — glyph
2998
- * finalize awaits {@link awaitTextStyleFontsReady} instead.
3179
+ * finalize awaits {@link awaitTextStyleFontsReady} (and the open-start
3180
+ * preset gate) instead.
3181
+ *
3182
+ * Drawing-independent preset faces are loaded separately via
3183
+ * {@link AcApDocManager.ensurePresetFontsForOpen} at open start.
2999
3184
  *
3000
3185
  * @param database - Database whose text style table has just been filled.
3001
3186
  */
3002
3187
  AcTrView2d.prototype.startTextStyleFontPreload = function (database) {
3003
- var _a;
3188
+ var _a, _b;
3004
3189
  var epoch = this._convertEpoch;
3005
3190
  if (this._textStyleFontPreloadEpoch === epoch &&
3006
3191
  this._textStyleFontPreloadPromise) {
3007
3192
  return;
3008
3193
  }
3009
3194
  this._textStyleFontPreloadEpoch = epoch;
3010
- var names = [];
3011
- try {
3012
- names = (_a = database.tables.textStyleTable.fonts) !== null && _a !== void 0 ? _a : [];
3013
- }
3014
- catch (_b) {
3015
- names = [];
3016
- }
3017
- // Style fonts alone are not enough: awaitFontsBeforeDraw only *awaits*
3018
- // content/style faces and kicks default/symbol fallbacks in the background.
3019
- // Drawings with empty primary font files (font falls back to the STYLE name)
3020
- // need those fallbacks loaded before the first glyph bake, otherwise Latin
3021
- // (and often all) text is permanently baked as '?'.
3195
+ // Worker mode: do not parse STYLE faces on the main thread (would dual-
3196
+ // parse mesh with workers). Each worker draw awaits its own content/style
3197
+ // faces via awaitFontsBeforeDraw. Preset fallbacks are gated separately
3198
+ // by ensurePresetFontsForOpen (scope: all).
3199
+ //
3200
+ // Main mode: gate deferred glyph jobs on style-table faces only. Unused
3201
+ // preset faces were already started at open — do not re-request here.
3202
+ var styleFonts = collectTextStyleFontNames(database);
3022
3203
  var fallbackFonts = FontManager.instance.getFontsToLoad();
3023
- var preloadNames = __spreadArray([], __read(new Set(__spreadArray(__spreadArray([], __read(names), false), __read(fallbackFonts), false))), false);
3024
- if (preloadNames.length === 0) {
3204
+ var firstDefault = __spreadArray([], __read(FontManager.instance.defaultFonts), false)[0];
3205
+ var plan = planTextStyleFontPreload(styleFonts, fallbackFonts, {
3206
+ firstDefaultFont: firstDefault
3207
+ });
3208
+ var mtextRenderer = AcTrMTextRenderer.getInstance();
3209
+ var parseSite = mtextRenderer.getRenderMode() === 'worker' ? 'worker' : 'main';
3210
+ var singleton = AcApDocManager;
3211
+ var preset = ((_b = (_a = singleton._instance) === null || _a === void 0 ? void 0 : _a.lastPresetFontsForOpen) === null || _b === void 0 ? void 0 : _b.length)
3212
+ ? __spreadArray([], __read(singleton._instance.lastPresetFontsForOpen), false) : __spreadArray([], __read(fallbackFonts), false);
3213
+ this._fontPreloadDiag = {
3214
+ critical: __spreadArray([], __read(plan.critical), false),
3215
+ workerWarm: [],
3216
+ background: [],
3217
+ preset: preset,
3218
+ workerSkipped: 0,
3219
+ parseSite: parseSite
3220
+ };
3221
+ if (parseSite === 'worker') {
3025
3222
  this._textStyleFontPreloadPromise = Promise.resolve();
3026
3223
  return;
3027
3224
  }
3028
- var mtextRenderer = AcTrMTextRenderer.getInstance();
3029
- this._textStyleFontPreloadPromise = Promise.all([
3030
- FontManager.instance.requestFonts(preloadNames),
3031
- // Worker isolates have their own FontManager; main-thread requestFonts
3032
- // alone does not populate them before asyncRenderMText.
3033
- mtextRenderer.loadFonts(fallbackFonts)
3034
- ]).then(function () { }, function () {
3035
- // Glyph draw still falls back via FontManager defaults / '?'.
3225
+ // Same deadline as AcApDocManager.installFontFileLoadTimeout.
3226
+ var preloadTimeoutMs = 30000;
3227
+ if (plan.critical.length === 0) {
3228
+ this._textStyleFontPreloadPromise = Promise.resolve();
3229
+ return;
3230
+ }
3231
+ var preload = FontManager.instance.requestFonts(plan.critical);
3232
+ this._textStyleFontPreloadPromise = new Promise(function (resolve) {
3233
+ var timer = setTimeout(function () {
3234
+ // Glyph draw still falls back via FontManager defaults / '?'.
3235
+ resolve();
3236
+ }, preloadTimeoutMs);
3237
+ preload.then(function () {
3238
+ clearTimeout(timer);
3239
+ resolve();
3240
+ }, function () {
3241
+ clearTimeout(timer);
3242
+ resolve();
3243
+ });
3036
3244
  });
3037
3245
  };
3038
3246
  /**
@@ -3072,45 +3280,54 @@ var AcTrView2d = /** @class */ (function (_super) {
3072
3280
  */
3073
3281
  AcTrView2d.prototype.finishEntityGeometry = function (threeEntity, _progressive) {
3074
3282
  return __awaiter(this, void 0, void 0, function () {
3075
- var needsGlyphDraw;
3283
+ var t0, isGroup, groupPending, needsGlyphDraw;
3076
3284
  return __generator(this, function (_a) {
3077
3285
  switch (_a.label) {
3078
3286
  case 0:
3079
- needsGlyphDraw = (threeEntity instanceof AcTrGroup &&
3080
- this.groupHasPendingGlyphGeometry(threeEntity)) ||
3287
+ t0 = performance.now();
3288
+ _a.label = 1;
3289
+ case 1:
3290
+ _a.trys.push([1, , 9, 10]);
3291
+ isGroup = threeEntity instanceof AcTrGroup;
3292
+ groupPending = isGroup && this.groupHasPendingGlyphGeometry(threeEntity);
3293
+ needsGlyphDraw = groupPending ||
3081
3294
  hasPendingComplexLineTypeGlyphs(threeEntity) ||
3082
3295
  (threeEntity instanceof AcTrGlyphEntity &&
3083
3296
  !threeEntity.hasDrawableGeometry());
3084
- if (!needsGlyphDraw) return [3 /*break*/, 2];
3085
- return [4 /*yield*/, this.awaitTextStyleFontsReady()];
3086
- case 1:
3087
- _a.sent();
3088
- _a.label = 2;
3297
+ if (!needsGlyphDraw) return [3 /*break*/, 3];
3298
+ return [4 /*yield*/, this.ensureDeferredFontsReady()];
3089
3299
  case 2:
3090
- if (!(threeEntity instanceof AcTrGroup)) return [3 /*break*/, 4];
3300
+ _a.sent();
3301
+ _a.label = 3;
3302
+ case 3:
3303
+ if (!isGroup) return [3 /*break*/, 5];
3091
3304
  // Linework-only INSERTs (no empty glyph shells) skip asyncDraw; spatial
3092
3305
  // boxes are refreshed by syncGroupSpatialBoundsForIndexing after commit.
3093
- if (!this.groupHasPendingGlyphGeometry(threeEntity)) {
3306
+ if (!groupPending) {
3094
3307
  return [2 /*return*/];
3095
3308
  }
3096
3309
  return [4 /*yield*/, threeEntity.asyncDraw()];
3097
- case 3:
3310
+ case 4:
3098
3311
  _a.sent();
3099
3312
  return [2 /*return*/];
3100
- case 4:
3101
- if (!hasPendingComplexLineTypeGlyphs(threeEntity)) return [3 /*break*/, 6];
3102
- return [4 /*yield*/, threeEntity.asyncDraw()];
3103
3313
  case 5:
3314
+ if (!hasPendingComplexLineTypeGlyphs(threeEntity)) return [3 /*break*/, 7];
3315
+ return [4 /*yield*/, threeEntity.asyncDraw()];
3316
+ case 6:
3104
3317
  _a.sent();
3105
3318
  return [2 /*return*/];
3106
- case 6:
3319
+ case 7:
3107
3320
  if (threeEntity.hasDrawableGeometry()) {
3108
3321
  return [2 /*return*/];
3109
3322
  }
3110
3323
  return [4 /*yield*/, threeEntity.asyncDraw()];
3111
- case 7:
3324
+ case 8:
3112
3325
  _a.sent();
3113
- return [2 /*return*/];
3326
+ return [3 /*break*/, 10];
3327
+ case 9:
3328
+ this._convertPhaseMs.finishGeometry += performance.now() - t0;
3329
+ return [7 /*endfinally*/];
3330
+ case 10: return [2 /*return*/];
3114
3331
  }
3115
3332
  });
3116
3333
  });
@@ -3269,13 +3486,73 @@ var AcTrView2d = /** @class */ (function (_super) {
3269
3486
  });
3270
3487
  };
3271
3488
  AcTrView2d.prototype.groupHasPendingGlyphGeometry = function (group) {
3272
- var pending = false;
3273
- group.traverse(function (child) {
3274
- if (child instanceof AcTrGlyphEntity && !child.hasDrawableGeometry()) {
3275
- pending = true;
3489
+ var e_14, _a;
3490
+ try {
3491
+ // Prefer O(block-def shells). A full THREE.traverse over a mega-block
3492
+ // (100k+ flattened mesh leaves) was dominating scene-convert wall time.
3493
+ for (var _b = __values(group.getSourceEntities()), _c = _b.next(); !_c.done; _c = _b.next()) {
3494
+ var entity = _c.value;
3495
+ if (entity instanceof AcTrGlyphEntity && !entity.hasDrawableGeometry()) {
3496
+ return true;
3497
+ }
3276
3498
  }
3277
- });
3278
- return pending;
3499
+ }
3500
+ catch (e_14_1) { e_14 = { error: e_14_1 }; }
3501
+ finally {
3502
+ try {
3503
+ if (_c && !_c.done && (_a = _b.return)) _a.call(_b);
3504
+ }
3505
+ finally { if (e_14) throw e_14.error; }
3506
+ }
3507
+ return AcTrView2d.directChildrenHavePendingGlyphs(group);
3508
+ };
3509
+ /**
3510
+ * Walks only {@link AcTrEntity} containers for empty glyph shells.
3511
+ *
3512
+ * Skips raw mesh/line leaves under a flattened {@link AcTrGroup} so checking
3513
+ * a whole-floor INSERT is O(glyph shells), not O(all drawable leaves).
3514
+ */
3515
+ AcTrView2d.directChildrenHavePendingGlyphs = function (root) {
3516
+ var e_15, _a;
3517
+ var children = root.children;
3518
+ for (var i = 0; i < children.length; i++) {
3519
+ var child = children[i];
3520
+ if (child instanceof AcTrGlyphEntity) {
3521
+ if (!child.hasDrawableGeometry()) {
3522
+ return true;
3523
+ }
3524
+ continue;
3525
+ }
3526
+ if (child instanceof AcTrGroup) {
3527
+ try {
3528
+ for (var _b = (e_15 = void 0, __values(child.getSourceEntities())), _c = _b.next(); !_c.done; _c = _b.next()) {
3529
+ var entity = _c.value;
3530
+ if (entity instanceof AcTrGlyphEntity &&
3531
+ !entity.hasDrawableGeometry()) {
3532
+ return true;
3533
+ }
3534
+ }
3535
+ }
3536
+ catch (e_15_1) { e_15 = { error: e_15_1 }; }
3537
+ finally {
3538
+ try {
3539
+ if (_c && !_c.done && (_a = _b.return)) _a.call(_b);
3540
+ }
3541
+ finally { if (e_15) throw e_15.error; }
3542
+ }
3543
+ if (AcTrView2d.directChildrenHavePendingGlyphs(child)) {
3544
+ return true;
3545
+ }
3546
+ continue;
3547
+ }
3548
+ if (child instanceof AcTrEntity) {
3549
+ // Nested non-group entity that may still host deferred glyph children.
3550
+ if (AcTrView2d.directChildrenHavePendingGlyphs(child)) {
3551
+ return true;
3552
+ }
3553
+ }
3554
+ }
3555
+ return false;
3279
3556
  };
3280
3557
  /**
3281
3558
  * Runs glyph/group geometry finalize off the main convert loop so other
@@ -3345,6 +3622,8 @@ var AcTrView2d = /** @class */ (function (_super) {
3345
3622
  this._pendingGeometryJobs = 0;
3346
3623
  this._textStyleFontPreloadPromise = null;
3347
3624
  this._textStyleFontPreloadEpoch = -1;
3625
+ this._deferredFontsReady = null;
3626
+ this._fontPreloadDiag = null;
3348
3627
  };
3349
3628
  /**
3350
3629
  * Waits until side-pool glyph/group jobs for the current convert epoch finish.
@@ -3388,7 +3667,7 @@ var AcTrView2d = /** @class */ (function (_super) {
3388
3667
  * paper layouts.
3389
3668
  */
3390
3669
  AcTrView2d.prototype.ensureViewportViews = function (blockTableRecord, layoutView) {
3391
- var e_14, _a;
3670
+ var e_16, _a;
3392
3671
  var iterator = blockTableRecord.newIterator();
3393
3672
  try {
3394
3673
  for (var iterator_2 = __values(iterator), iterator_2_1 = iterator_2.next(); !iterator_2_1.done; iterator_2_1 = iterator_2.next()) {
@@ -3401,12 +3680,12 @@ var AcTrView2d = /** @class */ (function (_super) {
3401
3680
  layoutView.addViewport(viewportView);
3402
3681
  }
3403
3682
  }
3404
- catch (e_14_1) { e_14 = { error: e_14_1 }; }
3683
+ catch (e_16_1) { e_16 = { error: e_16_1 }; }
3405
3684
  finally {
3406
3685
  try {
3407
3686
  if (iterator_2_1 && !iterator_2_1.done && (_a = iterator_2.return)) _a.call(iterator_2);
3408
3687
  }
3409
- finally { if (e_14) throw e_14.error; }
3688
+ finally { if (e_16) throw e_16.error; }
3410
3689
  }
3411
3690
  };
3412
3691
  /**
@@ -3434,14 +3713,14 @@ var AcTrView2d = /** @class */ (function (_super) {
3434
3713
  }
3435
3714
  }
3436
3715
  progressive = this._progressiveRendering && !options.forExport;
3437
- yieldGate = options.forExport
3716
+ yieldGate = options.forExport || !this._cooperativeYield
3438
3717
  ? undefined
3439
3718
  : new AcCmUiYieldGate(AcTrView2d.OPEN_CONVERT_YIELD_BUDGET_MS);
3440
3719
  yieldToEventLoop = function () {
3441
3720
  return new Promise(function (resolve) { return setTimeout(resolve, 0); });
3442
3721
  };
3443
3722
  _loop_4 = function (i) {
3444
- var entity, shouldConvert, objectId_1, convertGen_1, directMeta, added, superseded, threeEntity_1, isMultiLayerGroup, deferGeometry, isExtendBbox_1, commitEntity, layoutView, viewportView, fileName, error_2, didYield;
3723
+ var entity, shouldConvert, objectId_1, convertGen_1, directMeta, added, superseded, threeEntity_1, isMultiLayerGroup, deferGeometry, isExtendBbox_1, commitEntity, layoutView, viewportView, fileName, error_3, didYield;
3445
3724
  return __generator(this, function (_e) {
3446
3725
  switch (_e.label) {
3447
3726
  case 0:
@@ -3468,7 +3747,7 @@ var AcTrView2d = /** @class */ (function (_super) {
3468
3747
  AcTrViewportView.isDefaultPaperSpaceViewport(entity)) {
3469
3748
  return [2 /*return*/, "continue"];
3470
3749
  }
3471
- shouldConvert = options.forExport
3750
+ shouldConvert = options.forExport || this_3._convertInvisibleLayers
3472
3751
  ? this_3._entityDisplay.shouldConvertForExport(entity)
3473
3752
  : this_3._entityDisplay.shouldConvert(entity);
3474
3753
  if (!shouldConvert) {
@@ -3502,7 +3781,7 @@ var AcTrView2d = /** @class */ (function (_super) {
3502
3781
  this_3.applySessionHiddenObjectState(entity.objectId);
3503
3782
  if (progressive) {
3504
3783
  this_3.markProgressiveDirty();
3505
- this_3._progressiveOpenFit.afterGeometryBatch(function () { return _this.resolveLayoutFitBox(); }, i);
3784
+ this_3._progressiveOpenFit.afterGeometryBatch(function () { return _this.getDrawingExtents(); }, i);
3506
3785
  }
3507
3786
  }
3508
3787
  }
@@ -3550,6 +3829,7 @@ var AcTrView2d = /** @class */ (function (_super) {
3550
3829
  case 5:
3551
3830
  isExtendBbox_1 = !(entity instanceof AcDbRay || entity instanceof AcDbXline);
3552
3831
  commitEntity = function () { return __awaiter(_this, void 0, void 0, function () {
3832
+ var tAdd;
3553
3833
  var _this = this;
3554
3834
  var _a;
3555
3835
  return __generator(this, function (_b) {
@@ -3573,13 +3853,15 @@ var AcTrView2d = /** @class */ (function (_super) {
3573
3853
  this._inheritedLayerMaterialMapper.remap(threeEntity_1.children, '0', threeEntity_1.layerName);
3574
3854
  }
3575
3855
  }
3856
+ tAdd = performance.now();
3576
3857
  this._scene.addEntity(threeEntity_1, isExtendBbox_1);
3858
+ this._convertPhaseMs.addEntity += performance.now() - tAdd;
3577
3859
  this.applySessionHiddenObjectState(entity.objectId);
3578
3860
  // Release memory occupied by this entity
3579
3861
  threeEntity_1.dispose();
3580
3862
  if (progressive) {
3581
3863
  this.markProgressiveDirty();
3582
- this._progressiveOpenFit.afterGeometryBatch(function () { return _this.resolveLayoutFitBox(); }, i);
3864
+ this._progressiveOpenFit.afterGeometryBatch(function () { return _this.getDrawingExtents(); }, i);
3583
3865
  }
3584
3866
  return [2 /*return*/];
3585
3867
  }
@@ -3621,8 +3903,8 @@ var AcTrView2d = /** @class */ (function (_super) {
3621
3903
  }
3622
3904
  return [3 /*break*/, 11];
3623
3905
  case 9:
3624
- error_2 = _e.sent();
3625
- log.error("[AcTrView2d] Failed to convert entity ".concat(entity.objectId, " (").concat(entity.type, "):"), error_2);
3906
+ error_3 = _e.sent();
3907
+ log.error("[AcTrView2d] Failed to convert entity ".concat(entity.objectId, " (").concat(entity.type, "):"), error_3);
3626
3908
  return [3 /*break*/, 11];
3627
3909
  case 10:
3628
3910
  // Counter was reset in clear() when the epoch advanced; do not
@@ -3686,16 +3968,21 @@ var AcTrView2d = /** @class */ (function (_super) {
3686
3968
  };
3687
3969
  AcTrView2d.prototype.handleGroup = function (group_1, progressive_1) {
3688
3970
  return __awaiter(this, arguments, void 0, function (group, progressive, epoch, convertGen) {
3689
- var objectId, children, objectsGroupByLayer, children_1, children_1_1, child, renderContext, groupObjectId, groupLayerName, groupChildBoxes, aggregateSpatialBbox, registeredChildIndex;
3690
- var e_15, _a;
3971
+ var t0, objectId, children, objectsGroupByLayer_1, children_1, children_1_1, child, renderContext_1, groupObjectId_1, groupLayerName_1, groupChildBoxes_1, aggregateSpatialBbox_1, registeredChildIndex_1;
3972
+ var e_17, _a;
3691
3973
  var _this = this;
3692
3974
  var _b, _c;
3693
3975
  if (epoch === void 0) { epoch = this._convertEpoch; }
3694
3976
  if (convertGen === void 0) { convertGen = 0; }
3695
3977
  return __generator(this, function (_d) {
3696
3978
  switch (_d.label) {
3697
- case 0: return [4 /*yield*/, this.finishEntityGeometry(group, progressive)];
3979
+ case 0:
3980
+ t0 = performance.now();
3981
+ _d.label = 1;
3698
3982
  case 1:
3983
+ _d.trys.push([1, , 3, 4]);
3984
+ return [4 /*yield*/, this.finishEntityGeometry(group, progressive)];
3985
+ case 2:
3699
3986
  _d.sent();
3700
3987
  if (epoch !== this._convertEpoch) {
3701
3988
  group.dispose();
@@ -3709,17 +3996,17 @@ var AcTrView2d = /** @class */ (function (_super) {
3709
3996
  }
3710
3997
  this.syncGroupSpatialBoundsForIndexing(group);
3711
3998
  children = group.children;
3712
- objectsGroupByLayer = new Map();
3999
+ objectsGroupByLayer_1 = new Map();
3713
4000
  children.forEach(function (child) {
3714
4001
  var _a;
3715
4002
  if (child.visible === false) {
3716
4003
  return;
3717
4004
  }
3718
4005
  var layerName = child.userData.layerName;
3719
- if (!objectsGroupByLayer.has(layerName)) {
3720
- objectsGroupByLayer.set(layerName, []);
4006
+ if (!objectsGroupByLayer_1.has(layerName)) {
4007
+ objectsGroupByLayer_1.set(layerName, []);
3721
4008
  }
3722
- (_a = objectsGroupByLayer.get(layerName)) === null || _a === void 0 ? void 0 : _a.push(child);
4009
+ (_a = objectsGroupByLayer_1.get(layerName)) === null || _a === void 0 ? void 0 : _a.push(child);
3723
4010
  });
3724
4011
  // Important:
3725
4012
  // Sometimes one group may contain huge amount of objects (> 100,000). So it is important
@@ -3737,40 +4024,40 @@ var AcTrView2d = /** @class */ (function (_super) {
3737
4024
  child.parent = null;
3738
4025
  }
3739
4026
  }
3740
- catch (e_15_1) { e_15 = { error: e_15_1 }; }
4027
+ catch (e_17_1) { e_17 = { error: e_17_1 }; }
3741
4028
  finally {
3742
4029
  try {
3743
4030
  if (children_1_1 && !children_1_1.done && (_a = children_1.return)) _a.call(children_1);
3744
4031
  }
3745
- finally { if (e_15) throw e_15.error; }
4032
+ finally { if (e_17) throw e_17.error; }
3746
4033
  }
3747
- renderContext = group.renderContext;
3748
- groupObjectId = group.objectId;
3749
- groupLayerName = group.layerName;
4034
+ renderContext_1 = group.renderContext;
4035
+ groupObjectId_1 = group.objectId;
4036
+ groupLayerName_1 = group.layerName;
3750
4037
  // AcDbRenderingCache.draw (and similar paths such as AcDbTable) already call
3751
4038
  // applyMatrix on the group, which updates wcsBbbox and wcsChildBoxes to WCS.
3752
4039
  // Do not multiply group.matrix here — that would double-transform spatial bounds.
3753
4040
  if (process.env.NODE_ENV !== 'production') {
3754
4041
  assertAcTrGroupWcsBboxesConsistent(group);
3755
4042
  }
3756
- groupChildBoxes = group.wcsChildBoxes.map(function (box) { return ({
4043
+ groupChildBoxes_1 = group.wcsChildBoxes.map(function (box) { return ({
3757
4044
  minX: box.minX,
3758
4045
  minY: box.minY,
3759
4046
  maxX: box.maxX,
3760
4047
  maxY: box.maxY,
3761
4048
  id: box.id
3762
4049
  }); });
3763
- aggregateSpatialBbox = groupChildBoxes.length > 0
4050
+ aggregateSpatialBbox_1 = groupChildBoxes_1.length > 0
3764
4051
  ? unionGroupWcsChildBoxes(group)
3765
4052
  : group.wcsBbox.clone();
3766
- if (groupChildBoxes.length > 0) {
3767
- group.wcsBbox = aggregateSpatialBbox.clone();
4053
+ if (groupChildBoxes_1.length > 0) {
4054
+ group.wcsBbox = aggregateSpatialBbox_1.clone();
3768
4055
  }
3769
- registeredChildIndex = false;
3770
- objectsGroupByLayer.forEach(function (objects, layerName) {
4056
+ registeredChildIndex_1 = false;
4057
+ objectsGroupByLayer_1.forEach(function (objects, layerName) {
3771
4058
  // Nested layer-0 may already be resolved to an inner INSERT layer during
3772
4059
  // flatten. Remaining "0" buckets inherit this (outermost) INSERT layer.
3773
- var effectiveLayerName = layerName === '0' ? groupLayerName : layerName;
4060
+ var effectiveLayerName = layerName === '0' ? groupLayerName_1 : layerName;
3774
4061
  // Material remap must still treat authored layer-0 drawables as layer-0
3775
4062
  // ByLayer even when nest resolution already rewrote layerName.
3776
4063
  var sourceLayerForMaterials = objects.some(function (object) {
@@ -3788,23 +4075,23 @@ var AcTrView2d = /** @class */ (function (_super) {
3788
4075
  // render entity per layer bucket but preserve the INSERT object id for all
3789
4076
  // buckets, so selection/highlight still maps back to the same database object.
3790
4077
  // Within each layer bucket, the object id remains unique in scene indexing.
3791
- var entity = new AcTrEntity(renderContext);
4078
+ var entity = new AcTrEntity(renderContext_1);
3792
4079
  // Copy the INSERT matrix exactly — applyMatrix4 decomposes and drops
3793
4080
  // reflections from mirrored block scales.
3794
4081
  entity.matrix.copy(group.matrix);
3795
4082
  entity.matrixAutoUpdate = false;
3796
4083
  entity.matrixWorldNeedsUpdate = true;
3797
- entity.objectId = groupObjectId;
4084
+ entity.objectId = groupObjectId_1;
3798
4085
  entity.ownerId = group.ownerId;
3799
4086
  // If block-definition entities are on layer "0", this bucket now uses the layer
3800
4087
  // of the block reference itself (effectiveLayerName).
3801
4088
  entity.layerName = effectiveLayerName;
3802
- entity.userData.insertLayerName = groupLayerName;
3803
- entity.wcsBbox = aggregateSpatialBbox.clone();
4089
+ entity.userData.insertLayerName = groupLayerName_1;
4090
+ entity.wcsBbox = aggregateSpatialBbox_1.clone();
3804
4091
  var entityUserData = entity.userData;
3805
- if (!registeredChildIndex && groupChildBoxes.length > 0) {
3806
- entityUserData.spatialIndexChildBoxes = groupChildBoxes;
3807
- registeredChildIndex = true;
4092
+ if (!registeredChildIndex_1 && groupChildBoxes_1.length > 0) {
4093
+ entityUserData.spatialIndexChildBoxes = groupChildBoxes_1;
4094
+ registeredChildIndex_1 = true;
3808
4095
  }
3809
4096
  // Important:
3810
4097
  // DO NOT USE spread operator when adding objects because it may be one very large array
@@ -3814,18 +4101,24 @@ var AcTrView2d = /** @class */ (function (_super) {
3814
4101
  }
3815
4102
  entity.updateMatrixWorld(true);
3816
4103
  _this._layerAppearance.refreshTextMaterialsInObjectTree(entity);
4104
+ var tAdd = performance.now();
3817
4105
  _this._scene.addEntity(entity, true);
3818
- _this.applySessionHiddenObjectState(groupObjectId);
4106
+ _this._convertPhaseMs.addEntity += performance.now() - tAdd;
4107
+ _this.applySessionHiddenObjectState(groupObjectId_1);
3819
4108
  entity.dispose();
3820
4109
  });
3821
4110
  group.dispose();
3822
4111
  if (progressive) {
3823
4112
  this.markProgressiveDirty();
3824
4113
  this._progressiveOpenFit.afterGeometryBatch(function () {
3825
- return _this.resolveLayoutFitBox();
4114
+ return _this.getDrawingExtents();
3826
4115
  });
3827
4116
  }
3828
- return [2 /*return*/];
4117
+ return [3 /*break*/, 4];
4118
+ case 3:
4119
+ this._convertPhaseMs.handleGroup += performance.now() - t0;
4120
+ return [7 /*endfinally*/];
4121
+ case 4: return [2 /*return*/];
3829
4122
  }
3830
4123
  });
3831
4124
  });
@@ -3855,7 +4148,7 @@ var AcTrView2d = /** @class */ (function (_super) {
3855
4148
  if (!this._openLineworkFramePending || this.isConvertingEntities) {
3856
4149
  return;
3857
4150
  }
3858
- var box = this.resolveLayoutFitBox();
4151
+ var box = this.getDrawingExtents();
3859
4152
  if (!box || box.isEmpty()) {
3860
4153
  this._openLineworkFramePending = false;
3861
4154
  return;
@@ -3872,6 +4165,11 @@ var AcTrView2d = /** @class */ (function (_super) {
3872
4165
  AcTrView2d.prototype.stampEntityProcessingIdle = function () {
3873
4166
  if (this._numOfEntitiesToProcess === 0 && this._pendingGeometryJobs === 0) {
3874
4167
  this._entityProcessingIdleAt = performance.now();
4168
+ // Release block templates after INSERT convert/glyph work finishes.
4169
+ // Clearing at converter END was too early (convert still draining);
4170
+ // keeping templates until the next open kept baked shells in memory and
4171
+ // OOMed large drawings.
4172
+ AcDbRenderingCache.instance.clear();
3875
4173
  }
3876
4174
  };
3877
4175
  /**