@itwin/core-backend 5.1.0-dev.9 → 5.1.1

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 (671) hide show
  1. package/CHANGELOG.md +160 -1
  2. package/lib/cjs/BackendHubAccess.d.ts +1 -1
  3. package/lib/cjs/BackendHubAccess.js +1 -1
  4. package/lib/cjs/BackendHubAccess.js.map +1 -1
  5. package/lib/cjs/BackendLoggerCategory.js.map +1 -1
  6. package/lib/cjs/BisCoreSchema.d.ts.map +1 -1
  7. package/lib/cjs/BisCoreSchema.js +4 -2
  8. package/lib/cjs/BisCoreSchema.js.map +1 -1
  9. package/lib/cjs/BlobContainerService.js.map +1 -1
  10. package/lib/cjs/BriefcaseManager.d.ts +10 -2
  11. package/lib/cjs/BriefcaseManager.d.ts.map +1 -1
  12. package/lib/cjs/BriefcaseManager.js +16 -0
  13. package/lib/cjs/BriefcaseManager.js.map +1 -1
  14. package/lib/cjs/CatalogDb.js.map +1 -1
  15. package/lib/cjs/Category.d.ts +4 -4
  16. package/lib/cjs/Category.js +4 -4
  17. package/lib/cjs/Category.js.map +1 -1
  18. package/lib/cjs/ChangeSummaryManager.js +2 -2
  19. package/lib/cjs/ChangeSummaryManager.js.map +1 -1
  20. package/lib/cjs/ChangedElementsDb.js.map +1 -1
  21. package/lib/cjs/ChangesetECAdaptor.d.ts +67 -8
  22. package/lib/cjs/ChangesetECAdaptor.d.ts.map +1 -1
  23. package/lib/cjs/ChangesetECAdaptor.js +490 -275
  24. package/lib/cjs/ChangesetECAdaptor.js.map +1 -1
  25. package/lib/cjs/ChannelControl.js.map +1 -1
  26. package/lib/cjs/CheckpointManager.js.map +1 -1
  27. package/lib/cjs/ClassRegistry.d.ts +9 -1
  28. package/lib/cjs/ClassRegistry.d.ts.map +1 -1
  29. package/lib/cjs/ClassRegistry.js +14 -6
  30. package/lib/cjs/ClassRegistry.js.map +1 -1
  31. package/lib/cjs/CloudSqlite.js +1 -1
  32. package/lib/cjs/CloudSqlite.js.map +1 -1
  33. package/lib/cjs/CodeService.js.map +1 -1
  34. package/lib/cjs/CodeSpecs.d.ts +1 -1
  35. package/lib/cjs/CodeSpecs.js +1 -1
  36. package/lib/cjs/CodeSpecs.js.map +1 -1
  37. package/lib/cjs/ConcurrentQuery.js.map +1 -1
  38. package/lib/cjs/CustomViewState3dCreator.js.map +1 -1
  39. package/lib/cjs/DevTools.js.map +1 -1
  40. package/lib/cjs/DisplayStyle.d.ts +4 -4
  41. package/lib/cjs/DisplayStyle.js +3 -3
  42. package/lib/cjs/DisplayStyle.js.map +1 -1
  43. package/lib/cjs/ECDb.d.ts +4 -4
  44. package/lib/cjs/ECDb.d.ts.map +1 -1
  45. package/lib/cjs/ECDb.js +4 -4
  46. package/lib/cjs/ECDb.js.map +1 -1
  47. package/lib/cjs/ECSchemaXmlContext.js.map +1 -1
  48. package/lib/cjs/ECSqlStatement.d.ts +15 -6
  49. package/lib/cjs/ECSqlStatement.d.ts.map +1 -1
  50. package/lib/cjs/ECSqlStatement.js +19 -4
  51. package/lib/cjs/ECSqlStatement.js.map +1 -1
  52. package/lib/cjs/Element.d.ts +54 -51
  53. package/lib/cjs/Element.d.ts.map +1 -1
  54. package/lib/cjs/Element.js +67 -52
  55. package/lib/cjs/Element.js.map +1 -1
  56. package/lib/cjs/ElementAspect.d.ts +8 -8
  57. package/lib/cjs/ElementAspect.d.ts.map +1 -1
  58. package/lib/cjs/ElementAspect.js +8 -8
  59. package/lib/cjs/ElementAspect.js.map +1 -1
  60. package/lib/cjs/ElementGraphics.js.map +1 -1
  61. package/lib/cjs/ElementTreeWalker.js.map +1 -1
  62. package/lib/cjs/Entity.d.ts +10 -7
  63. package/lib/cjs/Entity.d.ts.map +1 -1
  64. package/lib/cjs/Entity.js +35 -13
  65. package/lib/cjs/Entity.js.map +1 -1
  66. package/lib/cjs/EntityReferences.js.map +1 -1
  67. package/lib/cjs/ExportGraphics.d.ts +54 -8
  68. package/lib/cjs/ExportGraphics.d.ts.map +1 -1
  69. package/lib/cjs/ExportGraphics.js +158 -59
  70. package/lib/cjs/ExportGraphics.js.map +1 -1
  71. package/lib/cjs/ExternalSource.js.map +1 -1
  72. package/lib/cjs/FontFile.js.map +1 -1
  73. package/lib/cjs/GeoCoordConfig.js.map +1 -1
  74. package/lib/cjs/GeographicCRSServices.d.ts +6 -2
  75. package/lib/cjs/GeographicCRSServices.d.ts.map +1 -1
  76. package/lib/cjs/GeographicCRSServices.js +1 -1
  77. package/lib/cjs/GeographicCRSServices.js.map +1 -1
  78. package/lib/cjs/GeometrySummary.js +47 -47
  79. package/lib/cjs/GeometrySummary.js.map +1 -1
  80. package/lib/cjs/IModelDb.d.ts +37 -26
  81. package/lib/cjs/IModelDb.d.ts.map +1 -1
  82. package/lib/cjs/IModelDb.js +132 -55
  83. package/lib/cjs/IModelDb.js.map +1 -1
  84. package/lib/cjs/IModelDbFonts.js.map +1 -1
  85. package/lib/cjs/IModelElementCloneContext.d.ts +1 -1
  86. package/lib/cjs/IModelElementCloneContext.d.ts.map +1 -1
  87. package/lib/cjs/IModelElementCloneContext.js +1 -1
  88. package/lib/cjs/IModelElementCloneContext.js.map +1 -1
  89. package/lib/cjs/IModelHost.d.ts +2 -3
  90. package/lib/cjs/IModelHost.d.ts.map +1 -1
  91. package/lib/cjs/IModelHost.js +2 -3
  92. package/lib/cjs/IModelHost.js.map +1 -1
  93. package/lib/cjs/IModelIncrementalSchemaLocater.d.ts +36 -0
  94. package/lib/cjs/IModelIncrementalSchemaLocater.d.ts.map +1 -0
  95. package/lib/cjs/IModelIncrementalSchemaLocater.js +69 -0
  96. package/lib/cjs/IModelIncrementalSchemaLocater.js.map +1 -0
  97. package/lib/cjs/IModelJsFs.js.map +1 -1
  98. package/lib/cjs/ImageSourceConversion.js.map +1 -1
  99. package/lib/cjs/IpcHost.js.map +1 -1
  100. package/lib/cjs/LineStyle.js.map +1 -1
  101. package/lib/cjs/LocalHub.d.ts.map +1 -1
  102. package/lib/cjs/LocalHub.js +6 -4
  103. package/lib/cjs/LocalHub.js.map +1 -1
  104. package/lib/cjs/LocalhostIpcHost.js.map +1 -1
  105. package/lib/cjs/LockControl.js.map +1 -1
  106. package/lib/cjs/Material.d.ts +4 -3
  107. package/lib/cjs/Material.d.ts.map +1 -1
  108. package/lib/cjs/Material.js +5 -5
  109. package/lib/cjs/Material.js.map +1 -1
  110. package/lib/cjs/Model.d.ts +22 -22
  111. package/lib/cjs/Model.js +22 -22
  112. package/lib/cjs/Model.js.map +1 -1
  113. package/lib/cjs/NativeAppStorage.js.map +1 -1
  114. package/lib/cjs/NativeHost.js.map +1 -1
  115. package/lib/cjs/NavigationRelationship.js.map +1 -1
  116. package/lib/cjs/PromiseMemoizer.js.map +1 -1
  117. package/lib/cjs/PropertyStore.js.map +1 -1
  118. package/lib/cjs/Relationship.d.ts +3 -0
  119. package/lib/cjs/Relationship.d.ts.map +1 -1
  120. package/lib/cjs/Relationship.js +15 -0
  121. package/lib/cjs/Relationship.js.map +1 -1
  122. package/lib/cjs/RpcBackend.js.map +1 -1
  123. package/lib/cjs/SQLiteDb.d.ts +1 -1
  124. package/lib/cjs/SQLiteDb.js +1 -1
  125. package/lib/cjs/SQLiteDb.js.map +1 -1
  126. package/lib/cjs/Schema.d.ts +25 -0
  127. package/lib/cjs/Schema.d.ts.map +1 -1
  128. package/lib/cjs/Schema.js +25 -0
  129. package/lib/cjs/Schema.js.map +1 -1
  130. package/lib/cjs/SchemaSync.js.map +1 -1
  131. package/lib/cjs/SchemaUtils.js.map +1 -1
  132. package/lib/cjs/SheetIndex.js.map +1 -1
  133. package/lib/cjs/SqliteChangesetReader.js.map +1 -1
  134. package/lib/cjs/SqliteStatement.d.ts +1 -1
  135. package/lib/cjs/SqliteStatement.d.ts.map +1 -1
  136. package/lib/cjs/SqliteStatement.js +1 -1
  137. package/lib/cjs/SqliteStatement.js.map +1 -1
  138. package/lib/cjs/Texture.d.ts +1 -1
  139. package/lib/cjs/Texture.js +1 -1
  140. package/lib/cjs/Texture.js.map +1 -1
  141. package/lib/cjs/TileStorage.js.map +1 -1
  142. package/lib/cjs/TxnManager.d.ts +4 -4
  143. package/lib/cjs/TxnManager.js +1 -1
  144. package/lib/cjs/TxnManager.js.map +1 -1
  145. package/lib/cjs/ViewDefinition.d.ts +40 -14
  146. package/lib/cjs/ViewDefinition.d.ts.map +1 -1
  147. package/lib/cjs/ViewDefinition.js +42 -14
  148. package/lib/cjs/ViewDefinition.js.map +1 -1
  149. package/lib/cjs/ViewStateHydrator.js.map +1 -1
  150. package/lib/cjs/ViewStore.js.map +1 -1
  151. package/lib/cjs/annotations/ElementDrivesTextAnnotation.d.ts +61 -0
  152. package/lib/cjs/annotations/ElementDrivesTextAnnotation.d.ts.map +1 -0
  153. package/lib/cjs/annotations/ElementDrivesTextAnnotation.js +110 -0
  154. package/lib/cjs/annotations/ElementDrivesTextAnnotation.js.map +1 -0
  155. package/lib/cjs/annotations/FrameGeometry.d.ts +51 -0
  156. package/lib/cjs/annotations/FrameGeometry.d.ts.map +1 -0
  157. package/lib/cjs/annotations/FrameGeometry.js +249 -0
  158. package/lib/cjs/annotations/FrameGeometry.js.map +1 -0
  159. package/lib/cjs/annotations/LeaderGeometry.d.ts +53 -0
  160. package/lib/cjs/annotations/LeaderGeometry.d.ts.map +1 -0
  161. package/lib/cjs/annotations/LeaderGeometry.js +184 -0
  162. package/lib/cjs/annotations/LeaderGeometry.js.map +1 -0
  163. package/lib/cjs/annotations/TextAnnotationElement.d.ts +204 -0
  164. package/lib/cjs/annotations/TextAnnotationElement.d.ts.map +1 -0
  165. package/lib/cjs/annotations/TextAnnotationElement.js +411 -0
  166. package/lib/cjs/annotations/TextAnnotationElement.js.map +1 -0
  167. package/lib/cjs/annotations/TextAnnotationGeometry.d.ts +33 -0
  168. package/lib/cjs/annotations/TextAnnotationGeometry.d.ts.map +1 -0
  169. package/lib/cjs/annotations/TextAnnotationGeometry.js +137 -0
  170. package/lib/cjs/annotations/TextAnnotationGeometry.js.map +1 -0
  171. package/lib/cjs/annotations/TextBlockGeometry.d.ts +16 -0
  172. package/lib/cjs/annotations/TextBlockGeometry.d.ts.map +1 -0
  173. package/lib/cjs/{TextAnnotationGeometry.js → annotations/TextBlockGeometry.js} +28 -70
  174. package/lib/cjs/annotations/TextBlockGeometry.js.map +1 -0
  175. package/lib/cjs/{TextAnnotationLayout.d.ts → annotations/TextBlockLayout.d.ts} +69 -22
  176. package/lib/cjs/annotations/TextBlockLayout.d.ts.map +1 -0
  177. package/lib/cjs/{TextAnnotationLayout.js → annotations/TextBlockLayout.js} +174 -49
  178. package/lib/cjs/annotations/TextBlockLayout.js.map +1 -0
  179. package/lib/cjs/assets/IModelChange.02.00.00.ecschema.xml +90 -90
  180. package/lib/cjs/assets/Settings/Schemas/Base.Schema.json +32 -32
  181. package/lib/cjs/assets/Settings/Schemas/Gcs.schema.json +27 -27
  182. package/lib/cjs/assets/Settings/Schemas/Workspace.Schema.json +94 -94
  183. package/lib/cjs/assets/Settings/backend.setting.json5 +21 -21
  184. package/lib/cjs/core-backend.d.ts +7 -3
  185. package/lib/cjs/core-backend.d.ts.map +1 -1
  186. package/lib/cjs/core-backend.js +27 -6
  187. package/lib/cjs/core-backend.js.map +1 -1
  188. package/lib/cjs/domains/FunctionalElements.js.map +1 -1
  189. package/lib/cjs/domains/FunctionalSchema.js.map +1 -1
  190. package/lib/cjs/domains/GenericElements.js.map +1 -1
  191. package/lib/cjs/domains/GenericSchema.js.map +1 -1
  192. package/lib/cjs/internal/ChangesetConflictArgs.js.map +1 -1
  193. package/lib/cjs/internal/ChannelAdmin.js.map +1 -1
  194. package/lib/cjs/internal/ElementLRUCache.d.ts +23 -0
  195. package/lib/cjs/internal/ElementLRUCache.d.ts.map +1 -1
  196. package/lib/cjs/internal/ElementLRUCache.js +167 -3
  197. package/lib/cjs/internal/ElementLRUCache.js.map +1 -1
  198. package/lib/cjs/internal/FontFileImpl.js.map +1 -1
  199. package/lib/cjs/internal/HubMock.js.map +1 -1
  200. package/lib/cjs/internal/IModelDbFontsImpl.js.map +1 -1
  201. package/lib/cjs/internal/NativePlatform.js.map +1 -1
  202. package/lib/cjs/internal/NoLocks.js.map +1 -1
  203. package/lib/cjs/internal/ServerBasedLocks.js.map +1 -1
  204. package/lib/cjs/internal/Symbols.d.ts +1 -0
  205. package/lib/cjs/internal/Symbols.d.ts.map +1 -1
  206. package/lib/cjs/internal/Symbols.js +2 -1
  207. package/lib/cjs/internal/Symbols.js.map +1 -1
  208. package/lib/cjs/internal/annotations/fields.d.ts +22 -0
  209. package/lib/cjs/internal/annotations/fields.d.ts.map +1 -0
  210. package/lib/cjs/internal/annotations/fields.js +237 -0
  211. package/lib/cjs/internal/annotations/fields.js.map +1 -0
  212. package/lib/cjs/internal/cross-package.js.map +1 -1
  213. package/lib/cjs/internal/workspace/SettingsImpl.js.map +1 -1
  214. package/lib/cjs/internal/workspace/SettingsSchemasImpl.js.map +1 -1
  215. package/lib/cjs/internal/workspace/WorkspaceImpl.js.map +1 -1
  216. package/lib/cjs/internal/workspace/WorkspaceSqliteDb.js.map +1 -1
  217. package/lib/cjs/rpc/multipart.js.map +1 -1
  218. package/lib/cjs/rpc/tracing.js.map +1 -1
  219. package/lib/cjs/rpc/web/logging.js.map +1 -1
  220. package/lib/cjs/rpc/web/request.js.map +1 -1
  221. package/lib/cjs/rpc/web/response.js.map +1 -1
  222. package/lib/cjs/rpc-impl/DevToolsRpcImpl.js.map +1 -1
  223. package/lib/cjs/rpc-impl/IModelReadRpcImpl.d.ts +1 -1
  224. package/lib/cjs/rpc-impl/IModelReadRpcImpl.js +1 -1
  225. package/lib/cjs/rpc-impl/IModelReadRpcImpl.js.map +1 -1
  226. package/lib/cjs/rpc-impl/IModelTileRpcImpl.js.map +1 -1
  227. package/lib/cjs/rpc-impl/RpcBriefcaseUtility.d.ts +2 -2
  228. package/lib/cjs/rpc-impl/RpcBriefcaseUtility.js.map +1 -1
  229. package/lib/cjs/rpc-impl/SnapshotIModelRpcImpl.d.ts +1 -1
  230. package/lib/cjs/rpc-impl/SnapshotIModelRpcImpl.js +1 -1
  231. package/lib/cjs/rpc-impl/SnapshotIModelRpcImpl.js.map +1 -1
  232. package/lib/cjs/workspace/Settings.js.map +1 -1
  233. package/lib/cjs/workspace/SettingsSchemas.js.map +1 -1
  234. package/lib/cjs/workspace/Workspace.d.ts +0 -1
  235. package/lib/cjs/workspace/Workspace.d.ts.map +1 -1
  236. package/lib/cjs/workspace/Workspace.js.map +1 -1
  237. package/lib/cjs/workspace/WorkspaceEditor.js.map +1 -1
  238. package/lib/esm/BackendHubAccess.d.ts +1 -1
  239. package/lib/esm/BackendHubAccess.js +1 -1
  240. package/lib/esm/BackendHubAccess.js.map +1 -1
  241. package/lib/esm/BackendLoggerCategory.js.map +1 -1
  242. package/lib/esm/BisCoreSchema.d.ts.map +1 -1
  243. package/lib/esm/BisCoreSchema.js +4 -2
  244. package/lib/esm/BisCoreSchema.js.map +1 -1
  245. package/lib/esm/BlobContainerService.js.map +1 -1
  246. package/lib/esm/BriefcaseManager.d.ts +10 -2
  247. package/lib/esm/BriefcaseManager.d.ts.map +1 -1
  248. package/lib/esm/BriefcaseManager.js +17 -1
  249. package/lib/esm/BriefcaseManager.js.map +1 -1
  250. package/lib/esm/CatalogDb.js.map +1 -1
  251. package/lib/esm/Category.d.ts +4 -4
  252. package/lib/esm/Category.js +4 -4
  253. package/lib/esm/Category.js.map +1 -1
  254. package/lib/esm/ChangeSummaryManager.js +2 -2
  255. package/lib/esm/ChangeSummaryManager.js.map +1 -1
  256. package/lib/esm/ChangedElementsDb.js.map +1 -1
  257. package/lib/esm/ChangesetECAdaptor.d.ts +67 -8
  258. package/lib/esm/ChangesetECAdaptor.d.ts.map +1 -1
  259. package/lib/esm/ChangesetECAdaptor.js +490 -275
  260. package/lib/esm/ChangesetECAdaptor.js.map +1 -1
  261. package/lib/esm/ChannelControl.js.map +1 -1
  262. package/lib/esm/CheckpointManager.js.map +1 -1
  263. package/lib/esm/ClassRegistry.d.ts +9 -1
  264. package/lib/esm/ClassRegistry.d.ts.map +1 -1
  265. package/lib/esm/ClassRegistry.js +14 -6
  266. package/lib/esm/ClassRegistry.js.map +1 -1
  267. package/lib/esm/CloudSqlite.js +1 -1
  268. package/lib/esm/CloudSqlite.js.map +1 -1
  269. package/lib/esm/CodeService.js.map +1 -1
  270. package/lib/esm/CodeSpecs.d.ts +1 -1
  271. package/lib/esm/CodeSpecs.js +1 -1
  272. package/lib/esm/CodeSpecs.js.map +1 -1
  273. package/lib/esm/ConcurrentQuery.js.map +1 -1
  274. package/lib/esm/CustomViewState3dCreator.js.map +1 -1
  275. package/lib/esm/DevTools.js.map +1 -1
  276. package/lib/esm/DisplayStyle.d.ts +4 -4
  277. package/lib/esm/DisplayStyle.js +3 -3
  278. package/lib/esm/DisplayStyle.js.map +1 -1
  279. package/lib/esm/ECDb.d.ts +4 -4
  280. package/lib/esm/ECDb.d.ts.map +1 -1
  281. package/lib/esm/ECDb.js +4 -4
  282. package/lib/esm/ECDb.js.map +1 -1
  283. package/lib/esm/ECSchemaXmlContext.js.map +1 -1
  284. package/lib/esm/ECSqlStatement.d.ts +15 -6
  285. package/lib/esm/ECSqlStatement.d.ts.map +1 -1
  286. package/lib/esm/ECSqlStatement.js +19 -4
  287. package/lib/esm/ECSqlStatement.js.map +1 -1
  288. package/lib/esm/Element.d.ts +54 -51
  289. package/lib/esm/Element.d.ts.map +1 -1
  290. package/lib/esm/Element.js +67 -52
  291. package/lib/esm/Element.js.map +1 -1
  292. package/lib/esm/ElementAspect.d.ts +8 -8
  293. package/lib/esm/ElementAspect.d.ts.map +1 -1
  294. package/lib/esm/ElementAspect.js +8 -8
  295. package/lib/esm/ElementAspect.js.map +1 -1
  296. package/lib/esm/ElementGraphics.js.map +1 -1
  297. package/lib/esm/ElementTreeWalker.js.map +1 -1
  298. package/lib/esm/Entity.d.ts +10 -7
  299. package/lib/esm/Entity.d.ts.map +1 -1
  300. package/lib/esm/Entity.js +36 -14
  301. package/lib/esm/Entity.js.map +1 -1
  302. package/lib/esm/EntityReferences.js.map +1 -1
  303. package/lib/esm/ExportGraphics.d.ts +54 -8
  304. package/lib/esm/ExportGraphics.d.ts.map +1 -1
  305. package/lib/esm/ExportGraphics.js +156 -58
  306. package/lib/esm/ExportGraphics.js.map +1 -1
  307. package/lib/esm/ExternalSource.js.map +1 -1
  308. package/lib/esm/FontFile.js.map +1 -1
  309. package/lib/esm/GeoCoordConfig.js.map +1 -1
  310. package/lib/esm/GeographicCRSServices.d.ts +6 -2
  311. package/lib/esm/GeographicCRSServices.d.ts.map +1 -1
  312. package/lib/esm/GeographicCRSServices.js +1 -1
  313. package/lib/esm/GeographicCRSServices.js.map +1 -1
  314. package/lib/esm/GeometrySummary.js +47 -47
  315. package/lib/esm/GeometrySummary.js.map +1 -1
  316. package/lib/esm/IModelDb.d.ts +37 -26
  317. package/lib/esm/IModelDb.d.ts.map +1 -1
  318. package/lib/esm/IModelDb.js +136 -59
  319. package/lib/esm/IModelDb.js.map +1 -1
  320. package/lib/esm/IModelDbFonts.js.map +1 -1
  321. package/lib/esm/IModelElementCloneContext.d.ts +1 -1
  322. package/lib/esm/IModelElementCloneContext.d.ts.map +1 -1
  323. package/lib/esm/IModelElementCloneContext.js +1 -1
  324. package/lib/esm/IModelElementCloneContext.js.map +1 -1
  325. package/lib/esm/IModelHost.d.ts +2 -3
  326. package/lib/esm/IModelHost.d.ts.map +1 -1
  327. package/lib/esm/IModelHost.js +2 -3
  328. package/lib/esm/IModelHost.js.map +1 -1
  329. package/lib/esm/IModelIncrementalSchemaLocater.d.ts +36 -0
  330. package/lib/esm/IModelIncrementalSchemaLocater.d.ts.map +1 -0
  331. package/lib/esm/IModelIncrementalSchemaLocater.js +65 -0
  332. package/lib/esm/IModelIncrementalSchemaLocater.js.map +1 -0
  333. package/lib/esm/IModelJsFs.js.map +1 -1
  334. package/lib/esm/ImageSourceConversion.js.map +1 -1
  335. package/lib/esm/IpcHost.js.map +1 -1
  336. package/lib/esm/LineStyle.js.map +1 -1
  337. package/lib/esm/LocalHub.d.ts.map +1 -1
  338. package/lib/esm/LocalHub.js +6 -4
  339. package/lib/esm/LocalHub.js.map +1 -1
  340. package/lib/esm/LocalhostIpcHost.js.map +1 -1
  341. package/lib/esm/LockControl.js.map +1 -1
  342. package/lib/esm/Material.d.ts +4 -3
  343. package/lib/esm/Material.d.ts.map +1 -1
  344. package/lib/esm/Material.js +5 -5
  345. package/lib/esm/Material.js.map +1 -1
  346. package/lib/esm/Model.d.ts +22 -22
  347. package/lib/esm/Model.js +22 -22
  348. package/lib/esm/Model.js.map +1 -1
  349. package/lib/esm/NativeAppStorage.js.map +1 -1
  350. package/lib/esm/NativeHost.js.map +1 -1
  351. package/lib/esm/NavigationRelationship.js.map +1 -1
  352. package/lib/esm/PromiseMemoizer.js.map +1 -1
  353. package/lib/esm/PropertyStore.js.map +1 -1
  354. package/lib/esm/Relationship.d.ts +3 -0
  355. package/lib/esm/Relationship.d.ts.map +1 -1
  356. package/lib/esm/Relationship.js +15 -0
  357. package/lib/esm/Relationship.js.map +1 -1
  358. package/lib/esm/RpcBackend.js.map +1 -1
  359. package/lib/esm/SQLiteDb.d.ts +1 -1
  360. package/lib/esm/SQLiteDb.js +1 -1
  361. package/lib/esm/SQLiteDb.js.map +1 -1
  362. package/lib/esm/Schema.d.ts +25 -0
  363. package/lib/esm/Schema.d.ts.map +1 -1
  364. package/lib/esm/Schema.js +25 -0
  365. package/lib/esm/Schema.js.map +1 -1
  366. package/lib/esm/SchemaSync.js.map +1 -1
  367. package/lib/esm/SchemaUtils.js.map +1 -1
  368. package/lib/esm/SheetIndex.js.map +1 -1
  369. package/lib/esm/SqliteChangesetReader.js.map +1 -1
  370. package/lib/esm/SqliteStatement.d.ts +1 -1
  371. package/lib/esm/SqliteStatement.d.ts.map +1 -1
  372. package/lib/esm/SqliteStatement.js +1 -1
  373. package/lib/esm/SqliteStatement.js.map +1 -1
  374. package/lib/esm/Texture.d.ts +1 -1
  375. package/lib/esm/Texture.js +1 -1
  376. package/lib/esm/Texture.js.map +1 -1
  377. package/lib/esm/TileStorage.js.map +1 -1
  378. package/lib/esm/TxnManager.d.ts +4 -4
  379. package/lib/esm/TxnManager.js +1 -1
  380. package/lib/esm/TxnManager.js.map +1 -1
  381. package/lib/esm/ViewDefinition.d.ts +40 -14
  382. package/lib/esm/ViewDefinition.d.ts.map +1 -1
  383. package/lib/esm/ViewDefinition.js +42 -14
  384. package/lib/esm/ViewDefinition.js.map +1 -1
  385. package/lib/esm/ViewStateHydrator.js.map +1 -1
  386. package/lib/esm/ViewStore.js.map +1 -1
  387. package/lib/esm/annotations/ElementDrivesTextAnnotation.d.ts +61 -0
  388. package/lib/esm/annotations/ElementDrivesTextAnnotation.d.ts.map +1 -0
  389. package/lib/esm/annotations/ElementDrivesTextAnnotation.js +105 -0
  390. package/lib/esm/annotations/ElementDrivesTextAnnotation.js.map +1 -0
  391. package/lib/esm/annotations/FrameGeometry.d.ts +51 -0
  392. package/lib/esm/annotations/FrameGeometry.d.ts.map +1 -0
  393. package/lib/esm/annotations/FrameGeometry.js +244 -0
  394. package/lib/esm/annotations/FrameGeometry.js.map +1 -0
  395. package/lib/esm/annotations/LeaderGeometry.d.ts +53 -0
  396. package/lib/esm/annotations/LeaderGeometry.d.ts.map +1 -0
  397. package/lib/esm/annotations/LeaderGeometry.js +179 -0
  398. package/lib/esm/annotations/LeaderGeometry.js.map +1 -0
  399. package/lib/esm/annotations/TextAnnotationElement.d.ts +204 -0
  400. package/lib/esm/annotations/TextAnnotationElement.d.ts.map +1 -0
  401. package/lib/esm/annotations/TextAnnotationElement.js +405 -0
  402. package/lib/esm/annotations/TextAnnotationElement.js.map +1 -0
  403. package/lib/esm/annotations/TextAnnotationGeometry.d.ts +33 -0
  404. package/lib/esm/annotations/TextAnnotationGeometry.d.ts.map +1 -0
  405. package/lib/esm/annotations/TextAnnotationGeometry.js +134 -0
  406. package/lib/esm/annotations/TextAnnotationGeometry.js.map +1 -0
  407. package/lib/esm/annotations/TextBlockGeometry.d.ts +16 -0
  408. package/lib/esm/annotations/TextBlockGeometry.d.ts.map +1 -0
  409. package/lib/esm/{TextAnnotationGeometry.js → annotations/TextBlockGeometry.js} +28 -70
  410. package/lib/esm/annotations/TextBlockGeometry.js.map +1 -0
  411. package/lib/esm/{TextAnnotationLayout.d.ts → annotations/TextBlockLayout.d.ts} +69 -22
  412. package/lib/esm/annotations/TextBlockLayout.d.ts.map +1 -0
  413. package/lib/esm/{TextAnnotationLayout.js → annotations/TextBlockLayout.js} +172 -48
  414. package/lib/esm/annotations/TextBlockLayout.js.map +1 -0
  415. package/lib/esm/core-backend.d.ts +7 -3
  416. package/lib/esm/core-backend.d.ts.map +1 -1
  417. package/lib/esm/core-backend.js +27 -3
  418. package/lib/esm/core-backend.js.map +1 -1
  419. package/lib/esm/domains/FunctionalElements.js.map +1 -1
  420. package/lib/esm/domains/FunctionalSchema.js.map +1 -1
  421. package/lib/esm/domains/GenericElements.js.map +1 -1
  422. package/lib/esm/domains/GenericSchema.js.map +1 -1
  423. package/lib/esm/internal/ChangesetConflictArgs.js.map +1 -1
  424. package/lib/esm/internal/ChannelAdmin.js.map +1 -1
  425. package/lib/esm/internal/ElementLRUCache.d.ts +23 -0
  426. package/lib/esm/internal/ElementLRUCache.d.ts.map +1 -1
  427. package/lib/esm/internal/ElementLRUCache.js +165 -2
  428. package/lib/esm/internal/ElementLRUCache.js.map +1 -1
  429. package/lib/esm/internal/FontFileImpl.js.map +1 -1
  430. package/lib/esm/internal/HubMock.js.map +1 -1
  431. package/lib/esm/internal/IModelDbFontsImpl.js.map +1 -1
  432. package/lib/esm/internal/NativePlatform.js.map +1 -1
  433. package/lib/esm/internal/NoLocks.js.map +1 -1
  434. package/lib/esm/internal/ServerBasedLocks.js.map +1 -1
  435. package/lib/esm/internal/Symbols.d.ts +1 -0
  436. package/lib/esm/internal/Symbols.d.ts.map +1 -1
  437. package/lib/esm/internal/Symbols.js +1 -0
  438. package/lib/esm/internal/Symbols.js.map +1 -1
  439. package/lib/esm/internal/annotations/fields.d.ts +22 -0
  440. package/lib/esm/internal/annotations/fields.d.ts.map +1 -0
  441. package/lib/esm/internal/annotations/fields.js +231 -0
  442. package/lib/esm/internal/annotations/fields.js.map +1 -0
  443. package/lib/esm/internal/cross-package.js.map +1 -1
  444. package/lib/esm/internal/workspace/SettingsImpl.js.map +1 -1
  445. package/lib/esm/internal/workspace/SettingsSchemasImpl.js.map +1 -1
  446. package/lib/esm/internal/workspace/WorkspaceImpl.js.map +1 -1
  447. package/lib/esm/internal/workspace/WorkspaceSqliteDb.js.map +1 -1
  448. package/lib/esm/rpc/multipart.js.map +1 -1
  449. package/lib/esm/rpc/tracing.js.map +1 -1
  450. package/lib/esm/rpc/web/logging.js.map +1 -1
  451. package/lib/esm/rpc/web/request.js.map +1 -1
  452. package/lib/esm/rpc/web/response.js.map +1 -1
  453. package/lib/esm/rpc-impl/DevToolsRpcImpl.js.map +1 -1
  454. package/lib/esm/rpc-impl/IModelReadRpcImpl.d.ts +1 -1
  455. package/lib/esm/rpc-impl/IModelReadRpcImpl.js +1 -1
  456. package/lib/esm/rpc-impl/IModelReadRpcImpl.js.map +1 -1
  457. package/lib/esm/rpc-impl/IModelTileRpcImpl.js.map +1 -1
  458. package/lib/esm/rpc-impl/RpcBriefcaseUtility.d.ts +2 -2
  459. package/lib/esm/rpc-impl/RpcBriefcaseUtility.js.map +1 -1
  460. package/lib/esm/rpc-impl/SnapshotIModelRpcImpl.d.ts +1 -1
  461. package/lib/esm/rpc-impl/SnapshotIModelRpcImpl.js +1 -1
  462. package/lib/esm/rpc-impl/SnapshotIModelRpcImpl.js.map +1 -1
  463. package/lib/esm/test/AdvancedEqual.js.map +1 -1
  464. package/lib/esm/test/AnnotationTestUtils.d.ts +15 -0
  465. package/lib/esm/test/AnnotationTestUtils.d.ts.map +1 -0
  466. package/lib/esm/test/AnnotationTestUtils.js +41 -0
  467. package/lib/esm/test/AnnotationTestUtils.js.map +1 -0
  468. package/lib/esm/test/AttachDb.test.js +11 -11
  469. package/lib/esm/test/AttachDb.test.js.map +1 -1
  470. package/lib/esm/test/ElementLRUCache.test.js +224 -1
  471. package/lib/esm/test/ElementLRUCache.test.js.map +1 -1
  472. package/lib/esm/test/GeometryTestUtil.js.map +1 -1
  473. package/lib/esm/test/IModelHost.test.js.map +1 -1
  474. package/lib/esm/test/IModelTestUtils.d.ts.map +1 -1
  475. package/lib/esm/test/IModelTestUtils.js +1 -0
  476. package/lib/esm/test/IModelTestUtils.js.map +1 -1
  477. package/lib/esm/test/ImageSourceConversion.test.js.map +1 -1
  478. package/lib/esm/test/IpcHost.test.js.map +1 -1
  479. package/lib/esm/test/KnownTestLocations.js.map +1 -1
  480. package/lib/esm/test/PrintElementTree.js.map +1 -1
  481. package/lib/esm/test/PropertyDb.test.js.map +1 -1
  482. package/lib/esm/test/RevisionUtility.js.map +1 -1
  483. package/lib/esm/test/SchemaUtils.test.js +25 -25
  484. package/lib/esm/test/SchemaUtils.test.js.map +1 -1
  485. package/lib/esm/test/SequentialLogMatcher.js.map +1 -1
  486. package/lib/esm/test/TestChangeSetUtility.js.map +1 -1
  487. package/lib/esm/test/TestUtils.d.ts +1 -1
  488. package/lib/esm/test/TestUtils.d.ts.map +1 -1
  489. package/lib/esm/test/TestUtils.js +1 -1
  490. package/lib/esm/test/TestUtils.js.map +1 -1
  491. package/lib/esm/test/annotations/Fields.test.d.ts +2 -0
  492. package/lib/esm/test/annotations/Fields.test.d.ts.map +1 -0
  493. package/lib/esm/test/annotations/Fields.test.js +576 -0
  494. package/lib/esm/test/annotations/Fields.test.js.map +1 -0
  495. package/lib/esm/test/annotations/FrameGeometry.test.d.ts +2 -0
  496. package/lib/esm/test/annotations/FrameGeometry.test.d.ts.map +1 -0
  497. package/lib/esm/test/annotations/FrameGeometry.test.js +86 -0
  498. package/lib/esm/test/annotations/FrameGeometry.test.js.map +1 -0
  499. package/lib/esm/test/annotations/LeaderGeometry.test.d.ts +2 -0
  500. package/lib/esm/test/annotations/LeaderGeometry.test.d.ts.map +1 -0
  501. package/lib/esm/test/annotations/LeaderGeometry.test.js +256 -0
  502. package/lib/esm/test/annotations/LeaderGeometry.test.js.map +1 -0
  503. package/lib/esm/test/annotations/TextAnnotation.test.js +269 -1047
  504. package/lib/esm/test/annotations/TextAnnotation.test.js.map +1 -1
  505. package/lib/esm/test/annotations/TextBlock.test.d.ts +2 -0
  506. package/lib/esm/test/annotations/TextBlock.test.d.ts.map +1 -0
  507. package/lib/esm/test/annotations/TextBlock.test.js +1199 -0
  508. package/lib/esm/test/annotations/TextBlock.test.js.map +1 -0
  509. package/lib/esm/test/assets/IncrementalSchemaLocater/configs/old.config.d.ts +60 -0
  510. package/lib/esm/test/assets/IncrementalSchemaLocater/configs/old.config.d.ts.map +1 -0
  511. package/lib/esm/test/assets/IncrementalSchemaLocater/configs/old.config.js +69 -0
  512. package/lib/esm/test/assets/IncrementalSchemaLocater/configs/old.config.js.map +1 -0
  513. package/lib/esm/test/assets/IncrementalSchemaLocater/configs/simple.config.d.ts +1442 -0
  514. package/lib/esm/test/assets/IncrementalSchemaLocater/configs/simple.config.d.ts.map +1 -0
  515. package/lib/esm/test/assets/IncrementalSchemaLocater/configs/simple.config.js +817 -0
  516. package/lib/esm/test/assets/IncrementalSchemaLocater/configs/simple.config.js.map +1 -0
  517. package/lib/esm/test/categories/Category.test.js.map +1 -1
  518. package/lib/esm/test/codespec/CodeSpec.test.js.map +1 -1
  519. package/lib/esm/test/ecdb/CTE.test.js +88 -88
  520. package/lib/esm/test/ecdb/CTE.test.js.map +1 -1
  521. package/lib/esm/test/ecdb/ConcurrentQuery.test.d.ts +2 -0
  522. package/lib/esm/test/ecdb/ConcurrentQuery.test.d.ts.map +1 -0
  523. package/lib/esm/test/ecdb/ConcurrentQuery.test.js +164 -0
  524. package/lib/esm/test/ecdb/ConcurrentQuery.test.js.map +1 -0
  525. package/lib/esm/test/ecdb/ConcurrentQueryLoad.test.js +35 -45
  526. package/lib/esm/test/ecdb/ConcurrentQueryLoad.test.js.map +1 -1
  527. package/lib/esm/test/ecdb/ECDb.test.js +86 -65
  528. package/lib/esm/test/ecdb/ECDb.test.js.map +1 -1
  529. package/lib/esm/test/ecdb/ECDbTestHelper.js.map +1 -1
  530. package/lib/esm/test/ecdb/ECSchemaXmlContext.test.js.map +1 -1
  531. package/lib/esm/test/ecdb/ECSqlAst.test.js +65 -65
  532. package/lib/esm/test/ecdb/ECSqlAst.test.js.map +1 -1
  533. package/lib/esm/test/ecdb/ECSqlQuery.test.js +0 -55
  534. package/lib/esm/test/ecdb/ECSqlQuery.test.js.map +1 -1
  535. package/lib/esm/test/ecdb/ECSqlReader.test.js +16 -16
  536. package/lib/esm/test/ecdb/ECSqlReader.test.js.map +1 -1
  537. package/lib/esm/test/ecdb/ECSqlStatement.test.js +484 -292
  538. package/lib/esm/test/ecdb/ECSqlStatement.test.js.map +1 -1
  539. package/lib/esm/test/ecdb/SqliteStatement.test.js.map +1 -1
  540. package/lib/esm/test/ecsql/dataset/ECSqlDatasets.js.map +1 -1
  541. package/lib/esm/test/ecsql/src/ECSqlTestGenerator.js +21 -21
  542. package/lib/esm/test/ecsql/src/ECSqlTestGenerator.js.map +1 -1
  543. package/lib/esm/test/ecsql/src/ECSqlTestParser.js.map +1 -1
  544. package/lib/esm/test/ecsql/src/ECSqlTestRunner.test.js.map +1 -1
  545. package/lib/esm/test/element/DeleteDefinitionElements.test.js.map +1 -1
  546. package/lib/esm/test/element/ElementAspect.test.js +22 -22
  547. package/lib/esm/test/element/ElementAspect.test.js.map +1 -1
  548. package/lib/esm/test/element/ElementDependencyGraph.test.js.map +1 -1
  549. package/lib/esm/test/element/ElementRoundTrip.test.js +139 -139
  550. package/lib/esm/test/element/ElementRoundTrip.test.js.map +1 -1
  551. package/lib/esm/test/element/ExcludedElements.test.js.map +1 -1
  552. package/lib/esm/test/element/ExternalSource.test.js.map +1 -1
  553. package/lib/esm/test/element/NullStructArray.test.js +13 -13
  554. package/lib/esm/test/element/NullStructArray.test.js.map +1 -1
  555. package/lib/esm/test/element/UrlLink.test.js.map +1 -1
  556. package/lib/esm/test/font/FontFile.test.js.map +1 -1
  557. package/lib/esm/test/font/IModelDbFonts.test.js.map +1 -1
  558. package/lib/esm/test/hubaccess/ApplyChangeset.test.d.ts +2 -0
  559. package/lib/esm/test/hubaccess/ApplyChangeset.test.d.ts.map +1 -0
  560. package/lib/esm/test/hubaccess/ApplyChangeset.test.js +86 -0
  561. package/lib/esm/test/hubaccess/ApplyChangeset.test.js.map +1 -0
  562. package/lib/esm/test/hubaccess/BriefcaseManager.test.js.map +1 -1
  563. package/lib/esm/test/hubaccess/CheckpointManager.test.js.map +1 -1
  564. package/lib/esm/test/imageData.js.map +1 -1
  565. package/lib/esm/test/imodel/ElementTreeWalker.test.js.map +1 -1
  566. package/lib/esm/test/imodel/GetTextureImage.test.js.map +1 -1
  567. package/lib/esm/test/imodel/IModel.test.js +313 -5
  568. package/lib/esm/test/imodel/IModel.test.js.map +1 -1
  569. package/lib/esm/test/imodel/ProjectExtents.test.js.map +1 -1
  570. package/lib/esm/test/imodel/SchemaXmlImport.test.js.map +1 -1
  571. package/lib/esm/test/incrementalSchemaLocater/ECSqlQueries.test.d.ts +2 -0
  572. package/lib/esm/test/incrementalSchemaLocater/ECSqlQueries.test.d.ts.map +1 -0
  573. package/lib/esm/test/incrementalSchemaLocater/ECSqlQueries.test.js +343 -0
  574. package/lib/esm/test/incrementalSchemaLocater/ECSqlQueries.test.js.map +1 -0
  575. package/lib/esm/test/incrementalSchemaLocater/IncrementalLoading.test.d.ts +2 -0
  576. package/lib/esm/test/incrementalSchemaLocater/IncrementalLoading.test.d.ts.map +1 -0
  577. package/lib/esm/test/incrementalSchemaLocater/IncrementalLoading.test.js +207 -0
  578. package/lib/esm/test/incrementalSchemaLocater/IncrementalLoading.test.js.map +1 -0
  579. package/lib/esm/test/incrementalSchemaLocater/utils/IModelSchemaLocater.d.ts +11 -0
  580. package/lib/esm/test/incrementalSchemaLocater/utils/IModelSchemaLocater.d.ts.map +1 -0
  581. package/lib/esm/test/incrementalSchemaLocater/utils/IModelSchemaLocater.js +36 -0
  582. package/lib/esm/test/incrementalSchemaLocater/utils/IModelSchemaLocater.js.map +1 -0
  583. package/lib/esm/test/incrementalSchemaLocater/utils/IncrementalTestHelper.d.ts +17 -0
  584. package/lib/esm/test/incrementalSchemaLocater/utils/IncrementalTestHelper.d.ts.map +1 -0
  585. package/lib/esm/test/incrementalSchemaLocater/utils/IncrementalTestHelper.js +116 -0
  586. package/lib/esm/test/incrementalSchemaLocater/utils/IncrementalTestHelper.js.map +1 -0
  587. package/lib/esm/test/incrementalSchemaLocater/utils/TestSqlSchemaLocater.d.ts +9 -0
  588. package/lib/esm/test/incrementalSchemaLocater/utils/TestSqlSchemaLocater.d.ts.map +1 -0
  589. package/lib/esm/test/incrementalSchemaLocater/utils/TestSqlSchemaLocater.js +20 -0
  590. package/lib/esm/test/incrementalSchemaLocater/utils/TestSqlSchemaLocater.js.map +1 -0
  591. package/lib/esm/test/index.js.map +1 -1
  592. package/lib/esm/test/misc/DevTools.test.js.map +1 -1
  593. package/lib/esm/test/misc/EntitySubClasses.test.js.map +1 -1
  594. package/lib/esm/test/misc/GeoServices.test.js +36 -10
  595. package/lib/esm/test/misc/GeoServices.test.js.map +1 -1
  596. package/lib/esm/test/misc/PromiseMemoizer.test.js.map +1 -1
  597. package/lib/esm/test/native/DgnDbWorker.test.js.map +1 -1
  598. package/lib/esm/test/rpc/response.test.js.map +1 -1
  599. package/lib/esm/test/schema/ClassRegistry.test.js +175 -73
  600. package/lib/esm/test/schema/ClassRegistry.test.js.map +1 -1
  601. package/lib/esm/test/schema/FunctionalDomain.test.js.map +1 -1
  602. package/lib/esm/test/schema/GenericDomain.test.js.map +1 -1
  603. package/lib/esm/test/schema/IModelSchemaContext.test.js.map +1 -1
  604. package/lib/esm/test/sheetindex/SheetIndex.test.js.map +1 -1
  605. package/lib/esm/test/standalone/ChangeMerge.test.js.map +1 -1
  606. package/lib/esm/test/standalone/ChangesetReader.test.js +575 -164
  607. package/lib/esm/test/standalone/ChangesetReader.test.js.map +1 -1
  608. package/lib/esm/test/standalone/CustomViewState3dCreator.test.js.map +1 -1
  609. package/lib/esm/test/standalone/DisplayStyle.test.js.map +1 -1
  610. package/lib/esm/test/standalone/Drawing.test.js.map +1 -1
  611. package/lib/esm/test/standalone/ElementGraphics.test.js.map +1 -1
  612. package/lib/esm/test/standalone/ElementMesh.test.js.map +1 -1
  613. package/lib/esm/test/standalone/ExportGraphics.test.js +67 -15
  614. package/lib/esm/test/standalone/ExportGraphics.test.js.map +1 -1
  615. package/lib/esm/test/standalone/GeometryChangeEvents.test.js.map +1 -1
  616. package/lib/esm/test/standalone/GeometryStream.test.js +49 -1
  617. package/lib/esm/test/standalone/GeometryStream.test.js.map +1 -1
  618. package/lib/esm/test/standalone/HubMock.test.js.map +1 -1
  619. package/lib/esm/test/standalone/IModelLimits.test.d.ts +2 -0
  620. package/lib/esm/test/standalone/IModelLimits.test.d.ts.map +1 -0
  621. package/lib/esm/test/standalone/IModelLimits.test.js +103 -0
  622. package/lib/esm/test/standalone/IModelLimits.test.js.map +1 -0
  623. package/lib/esm/test/standalone/IModelWrite.test.js +27 -27
  624. package/lib/esm/test/standalone/IModelWrite.test.js.map +1 -1
  625. package/lib/esm/test/standalone/InlineGeometryPartReferences.test.js.map +1 -1
  626. package/lib/esm/test/standalone/MergeConflict.test.js.map +1 -1
  627. package/lib/esm/test/standalone/NativeAppStorage.test.js.map +1 -1
  628. package/lib/esm/test/standalone/RenderMaterialElement.test.js +24 -1
  629. package/lib/esm/test/standalone/RenderMaterialElement.test.js.map +1 -1
  630. package/lib/esm/test/standalone/RenderTimeline.test.js.map +1 -1
  631. package/lib/esm/test/standalone/SQLiteDb.test.js.map +1 -1
  632. package/lib/esm/test/standalone/SchemaUtils.test.js.map +1 -1
  633. package/lib/esm/test/standalone/SectionDrawing.test.js.map +1 -1
  634. package/lib/esm/test/standalone/ServerBasedLocks.test.js.map +1 -1
  635. package/lib/esm/test/standalone/Setting.test.js.map +1 -1
  636. package/lib/esm/test/standalone/Settings.test.js.map +1 -1
  637. package/lib/esm/test/standalone/SettingsSchemas.test.js.map +1 -1
  638. package/lib/esm/test/standalone/SnapshotDb.test.js +19 -1
  639. package/lib/esm/test/standalone/SnapshotDb.test.js.map +1 -1
  640. package/lib/esm/test/standalone/Texture.test.js.map +1 -1
  641. package/lib/esm/test/standalone/TileCache.test.js.map +1 -1
  642. package/lib/esm/test/standalone/TileTree.test.js.map +1 -1
  643. package/lib/esm/test/standalone/TxnManager.test.js.map +1 -1
  644. package/lib/esm/test/standalone/ViewDefinition.test.js.map +1 -1
  645. package/lib/esm/test/standalone/ViewStoreDb.test.js.map +1 -1
  646. package/lib/esm/test/standalone/Workspace.test.js.map +1 -1
  647. package/lib/esm/workspace/Settings.js.map +1 -1
  648. package/lib/esm/workspace/SettingsSchemas.js.map +1 -1
  649. package/lib/esm/workspace/Workspace.d.ts +0 -1
  650. package/lib/esm/workspace/Workspace.d.ts.map +1 -1
  651. package/lib/esm/workspace/Workspace.js.map +1 -1
  652. package/lib/esm/workspace/WorkspaceEditor.js.map +1 -1
  653. package/package.json +22 -16
  654. package/lib/cjs/TextAnnotationElement.d.ts +0 -54
  655. package/lib/cjs/TextAnnotationElement.d.ts.map +0 -1
  656. package/lib/cjs/TextAnnotationElement.js +0 -94
  657. package/lib/cjs/TextAnnotationElement.js.map +0 -1
  658. package/lib/cjs/TextAnnotationGeometry.d.ts +0 -32
  659. package/lib/cjs/TextAnnotationGeometry.d.ts.map +0 -1
  660. package/lib/cjs/TextAnnotationGeometry.js.map +0 -1
  661. package/lib/cjs/TextAnnotationLayout.d.ts.map +0 -1
  662. package/lib/cjs/TextAnnotationLayout.js.map +0 -1
  663. package/lib/esm/TextAnnotationElement.d.ts +0 -54
  664. package/lib/esm/TextAnnotationElement.d.ts.map +0 -1
  665. package/lib/esm/TextAnnotationElement.js +0 -89
  666. package/lib/esm/TextAnnotationElement.js.map +0 -1
  667. package/lib/esm/TextAnnotationGeometry.d.ts +0 -32
  668. package/lib/esm/TextAnnotationGeometry.d.ts.map +0 -1
  669. package/lib/esm/TextAnnotationGeometry.js.map +0 -1
  670. package/lib/esm/TextAnnotationLayout.d.ts.map +0 -1
  671. package/lib/esm/TextAnnotationLayout.js.map +0 -1
@@ -0,0 +1,1199 @@
1
+ /*---------------------------------------------------------------------------------------------
2
+ * Copyright (c) Bentley Systems, Incorporated. All rights reserved.
3
+ * See LICENSE.md in the project root for license terms and full copyright notice.
4
+ *--------------------------------------------------------------------------------------------*/
5
+ import { expect } from "chai";
6
+ import { computeGraphemeOffsets, layoutTextBlock, TextStyleResolver } from "../../annotations/TextBlockLayout";
7
+ import { Geometry } from "@itwin/core-geometry";
8
+ import { ColorDef, FontType, FractionRun, LineBreakRun, Paragraph, TabRun, TextAnnotation, TextBlock, TextRun, TextStyleSettings } from "@itwin/core-common";
9
+ import { IModelTestUtils } from "../IModelTestUtils";
10
+ import { ProcessDetector } from "@itwin/core-bentley";
11
+ import { produceTextBlockGeometry } from "../../core-backend";
12
+ import { computeTextRangeAsStringLength, doLayout } from "../AnnotationTestUtils";
13
+ function makeTextRun(content) {
14
+ return TextRun.create({ content });
15
+ }
16
+ function isIntlSupported() {
17
+ // Node in the mobile add-on does not include Intl, so this test fails. Right now, mobile
18
+ // users are not expected to do any editing, but long term we will attempt to find a better
19
+ // solution.
20
+ return !ProcessDetector.isMobileAppBackend;
21
+ }
22
+ function findTextStyleImpl(id) {
23
+ if (id === "0x42") {
24
+ return TextStyleSettings.fromJSON({ lineSpacingFactor: 12, fontName: "block", isBold: true });
25
+ }
26
+ return TextStyleSettings.fromJSON({ lineSpacingFactor: 1, fontName: "other" });
27
+ }
28
+ describe("layoutTextBlock", () => {
29
+ describe("resolves TextStyleSettings", () => {
30
+ it("inherits styling from TextBlock when Paragraph and Run have no style overrides", () => {
31
+ const textBlock = TextBlock.create({ styleId: "0x42" });
32
+ const run = TextRun.create({ content: "test" });
33
+ textBlock.appendParagraph();
34
+ textBlock.appendRun(run);
35
+ const tb = doLayout(textBlock, {
36
+ findTextStyle: findTextStyleImpl,
37
+ });
38
+ expect(tb.lines.length).to.equal(1);
39
+ expect(tb.lines[0].runs.length).to.equal(1);
40
+ const runStyle = tb.lines[0].runs[0].style;
41
+ expect(runStyle.fontName).to.equal("block");
42
+ expect(runStyle.lineSpacingFactor).to.equal(12);
43
+ expect(runStyle.isBold).to.be.true;
44
+ });
45
+ it("inherits style overrides from Paragraph when Run has no style overrides", () => {
46
+ const textBlock = TextBlock.create({ styleId: "0x42" });
47
+ const paragraph = Paragraph.create({ styleOverrides: { fontName: "paragraph" } });
48
+ const run = TextRun.create({ content: "test" });
49
+ textBlock.paragraphs.push(paragraph);
50
+ textBlock.appendRun(run);
51
+ const tb = doLayout(textBlock, {
52
+ findTextStyle: findTextStyleImpl,
53
+ });
54
+ expect(tb.lines.length).to.equal(1);
55
+ expect(tb.lines[0].runs.length).to.equal(1);
56
+ const runStyle = tb.lines[0].runs[0].style;
57
+ expect(runStyle.fontName).to.equal("paragraph");
58
+ expect(runStyle.isBold).to.be.true;
59
+ });
60
+ it("uses Run style overrides when Run has overrides", () => {
61
+ const textBlock = TextBlock.create({ styleId: "0x42" });
62
+ const paragraph = Paragraph.create({ styleOverrides: { lineSpacingFactor: 55, fontName: "paragraph" } });
63
+ const run = TextRun.create({ content: "test", styleOverrides: { lineSpacingFactor: 99, fontName: "run" } });
64
+ textBlock.paragraphs.push(paragraph);
65
+ textBlock.appendRun(run);
66
+ const tb = doLayout(textBlock, {
67
+ findTextStyle: findTextStyleImpl,
68
+ });
69
+ expect(tb.lines.length).to.equal(1);
70
+ expect(tb.lines[0].runs.length).to.equal(1);
71
+ const runStyle = tb.lines[0].runs[0].style;
72
+ expect(runStyle.fontName).to.equal("run");
73
+ expect(runStyle.isBold).to.be.true;
74
+ });
75
+ it("still uses TextBlock specific styles when Run has style overrides", () => {
76
+ // Some style settings only make sense on a TextBlock, so they are always applied from the TextBlock, even if the Run has a style override.
77
+ const textBlock = TextBlock.create({ styleId: "0x42" });
78
+ const run = TextRun.create({ content: "test", styleOverrides: { lineSpacingFactor: 99, fontName: "run" } });
79
+ textBlock.appendParagraph();
80
+ textBlock.appendRun(run);
81
+ const tb = doLayout(textBlock, {
82
+ findTextStyle: findTextStyleImpl,
83
+ });
84
+ expect(tb.lines.length).to.equal(1);
85
+ expect(tb.lines[0].runs.length).to.equal(1);
86
+ const runStyle = tb.lines[0].runs[0].style;
87
+ expect(runStyle.lineSpacingFactor).to.equal(12);
88
+ });
89
+ it("inherits overrides from TextBlock, Paragraph and Run when there is no styleId", () => {
90
+ const textBlock = TextBlock.create({ styleId: "", styleOverrides: { widthFactor: 34, lineHeight: 3, lineSpacingFactor: 12, isBold: true } });
91
+ const paragraph = Paragraph.create({ styleOverrides: { lineHeight: 56, color: 0xff0000, frame: { shape: "octagon" } } });
92
+ const run = TextRun.create({ content: "test", styleOverrides: { widthFactor: 78, fontName: "override", leader: { wantElbow: true } } });
93
+ textBlock.paragraphs.push(paragraph);
94
+ textBlock.appendRun(run);
95
+ const tb = doLayout(textBlock, {
96
+ findTextStyle: findTextStyleImpl,
97
+ });
98
+ expect(tb.lines.length).to.equal(1);
99
+ expect(tb.lines[0].runs.length).to.equal(1);
100
+ const runStyle = tb.lines[0].runs[0].style;
101
+ // widthFactor is always taken from the TextBlock, even if the Run has overrides
102
+ expect(runStyle.widthFactor).to.equal(34);
103
+ // lineHeight is always taken from the TextBlock, even if the Run has overrides
104
+ expect(runStyle.lineHeight).to.equal(3);
105
+ // lineSpacingFactor is always taken from the TextBlock, even if the Run has overrides
106
+ expect(runStyle.lineSpacingFactor).to.equal(12);
107
+ // frame settings are always taken from the TextBlock, even if the Paragraph or Run has overrides
108
+ expect(runStyle.frame.shape).to.equal("none");
109
+ // leader settings are always taken from the TextBlock, even if the Paragraph or Run has overrides
110
+ expect(runStyle.leader.wantElbow).to.be.false;
111
+ expect(runStyle.fontName).to.equal("override");
112
+ expect(runStyle.color).to.equal(0xff0000);
113
+ expect(runStyle.isBold).to.be.true;
114
+ });
115
+ it("does not inherit overrides in TextBlock or Paragraph when Run has same propertied overriden - unless they are TextBlock specific settings", () => {
116
+ const textBlock = TextBlock.create({ styleId: "0x42", styleOverrides: { widthFactor: 34, lineHeight: 3, lineSpacingFactor: 12, isBold: true } });
117
+ const paragraph = Paragraph.create({ styleOverrides: { lineHeight: 56, color: 0xff0000 } });
118
+ const run = TextRun.create({ content: "test", styleOverrides: { widthFactor: 78, lineHeight: 6, lineSpacingFactor: 24, fontName: "override", isBold: false } });
119
+ textBlock.paragraphs.push(paragraph);
120
+ textBlock.appendRun(run);
121
+ const tb = doLayout(textBlock, {
122
+ findTextStyle: findTextStyleImpl,
123
+ });
124
+ expect(tb.lines.length).to.equal(1);
125
+ expect(tb.lines[0].runs.length).to.equal(1);
126
+ const runStyle = tb.lines[0].runs[0].style;
127
+ // widthFactor is always taken from the TextBlock, even if the Run has a styleId or overrides
128
+ expect(runStyle.widthFactor).to.equal(34);
129
+ // lineHeight is always taken from the TextBlock, even if the Run has a styleId or overrides
130
+ expect(runStyle.lineHeight).to.equal(3);
131
+ // lineSpacingFactor is always taken from the TextBlock, even if the Run has a styleId or overrides
132
+ expect(runStyle.lineSpacingFactor).to.equal(12);
133
+ expect(runStyle.fontName).to.equal("override");
134
+ expect(runStyle.color).to.equal(0xff0000);
135
+ expect(runStyle.isBold).to.be.false;
136
+ });
137
+ it("takes child overrides over parent overrides", () => {
138
+ //...unless they are TextBlock specific as covered in other tests
139
+ const textBlock = TextBlock.create({ styleId: "", styleOverrides: { fontName: "grandparent" } });
140
+ const paragraph = Paragraph.create({ styleOverrides: { fontName: "parent" } });
141
+ const run = TextRun.create({ content: "test", styleOverrides: { fontName: "child" } });
142
+ textBlock.paragraphs.push(paragraph);
143
+ textBlock.appendRun(run);
144
+ const tb = doLayout(textBlock, {
145
+ findTextStyle: findTextStyleImpl,
146
+ });
147
+ expect(tb.lines.length).to.equal(1);
148
+ expect(tb.lines[0].runs.length).to.equal(1);
149
+ const runStyle = tb.lines[0].runs[0].style;
150
+ expect(runStyle.fontName).to.equal("child");
151
+ });
152
+ });
153
+ it("has consistent data when converted to a layout result", function () {
154
+ if (!isIntlSupported()) {
155
+ this.skip();
156
+ }
157
+ // Initialize a new TextBlockLayout object
158
+ const textBlock = TextBlock.create({ width: 50, styleId: "", styleOverrides: { widthFactor: 34, color: 0x00ff00, fontName: "arial" } });
159
+ const run0 = TextRun.create({
160
+ content: "Lorem ipsum dolor sit amet, consectetur adipiscing elit. Phasellus pretium mi sit amet magna malesuada, at venenatis ante eleifend.",
161
+ styleOverrides: { lineHeight: 56, color: 0xff0000 },
162
+ });
163
+ const run1 = TextRun.create({
164
+ content: "Donec sit amet semper sapien. Nullam commodo, libero a accumsan lacinia, metus enim pharetra lacus, eu facilisis sem nisi eu dui.",
165
+ styleOverrides: { widthFactor: 78, fontName: "run1" },
166
+ });
167
+ const run2 = TextRun.create({
168
+ content: "Duis dui quam, suscipit quis feugiat id, fermentum ut augue. Mauris iaculis odio rhoncus lorem eleifend, posuere viverra turpis elementum.",
169
+ styleOverrides: {},
170
+ });
171
+ const fractionRun = FractionRun.create({ numerator: "num", denominator: "denom", styleOverrides: {} });
172
+ textBlock.appendRun(run0);
173
+ textBlock.appendRun(fractionRun);
174
+ textBlock.appendParagraph();
175
+ textBlock.appendRun(run1);
176
+ textBlock.appendRun(run2);
177
+ // Call the toResult() method
178
+ const textBlockLayout = doLayout(textBlock, {
179
+ findFontId: (fontName) => {
180
+ if (fontName === "arial") {
181
+ return 1;
182
+ }
183
+ else if (fontName === "run1") {
184
+ return 2;
185
+ }
186
+ return 0;
187
+ },
188
+ });
189
+ const result = textBlockLayout.toResult();
190
+ // Assert that the result object has the same data as the original TextBlockLayout object
191
+ expect(result.range).to.deep.equal(textBlockLayout.range.toJSON());
192
+ expect(result.lines.length).to.equal(textBlockLayout.lines.length);
193
+ // Loop through each line in the result and the original object
194
+ for (let i = 0; i < result.lines.length; i++) {
195
+ const resultLine = result.lines[i];
196
+ const originalLine = textBlockLayout.lines[i];
197
+ // Source paragraph index matches
198
+ expect(resultLine.sourceParagraphIndex).to.equal(textBlock.paragraphs.indexOf(originalLine.source));
199
+ // Ranges match
200
+ expect(resultLine.range).to.deep.equal(originalLine.range.toJSON());
201
+ expect(resultLine.justificationRange).to.deep.equal(originalLine.justificationRange.toJSON());
202
+ // Offset matches
203
+ expect(resultLine.offsetFromDocument).to.deep.equal(originalLine.offsetFromDocument);
204
+ for (let j = 0; j < resultLine.runs.length; j++) {
205
+ const resultRun = resultLine.runs[j];
206
+ const originalRun = originalLine.runs[j];
207
+ // Source run index matches
208
+ expect(resultRun.sourceRunIndex).to.equal(textBlock.paragraphs[resultLine.sourceParagraphIndex].runs.indexOf(originalRun.source));
209
+ // FontId matches
210
+ expect(resultRun.fontId).to.equal(originalRun.fontId);
211
+ // Offsets match
212
+ expect(resultRun.characterOffset).to.equal(originalRun.charOffset);
213
+ expect(resultRun.characterCount).to.equal(originalRun.numChars);
214
+ expect(resultRun.offsetFromLine).to.deep.equal(originalRun.offsetFromLine);
215
+ // Range matches
216
+ expect(resultRun.range).to.deep.equal(originalRun.range.toJSON());
217
+ // Text style matches
218
+ expect(resultRun.textStyle).to.deep.equal(originalRun.style.toJSON());
219
+ // Optional values match existence and values
220
+ if (resultRun.justificationRange) {
221
+ expect(originalRun.justificationRange);
222
+ }
223
+ if (originalRun.justificationRange) {
224
+ expect(resultRun.justificationRange);
225
+ }
226
+ if (resultRun.justificationRange && originalRun.justificationRange) {
227
+ expect(resultRun.justificationRange).to.deep.equal(originalRun.justificationRange.toJSON());
228
+ }
229
+ if (resultRun.numeratorRange) {
230
+ expect(originalRun.numeratorRange);
231
+ }
232
+ if (originalRun.numeratorRange) {
233
+ expect(resultRun.numeratorRange);
234
+ }
235
+ if (resultRun.numeratorRange && originalRun.numeratorRange) {
236
+ expect(resultRun.numeratorRange).to.deep.equal(originalRun.numeratorRange.toJSON());
237
+ }
238
+ if (resultRun.denominatorRange) {
239
+ expect(originalRun.denominatorRange);
240
+ }
241
+ if (originalRun.denominatorRange) {
242
+ expect(resultRun.denominatorRange);
243
+ }
244
+ if (resultRun.denominatorRange && originalRun.denominatorRange) {
245
+ expect(resultRun.denominatorRange).to.deep.equal(originalRun.denominatorRange.toJSON());
246
+ }
247
+ // Check that the result string matches what we expect
248
+ const inputRun = textBlock.paragraphs[resultLine.sourceParagraphIndex].runs[resultRun.sourceRunIndex].clone();
249
+ if (inputRun.type === "text") {
250
+ const resultText = inputRun.content.substring(resultRun.characterOffset, resultRun.characterOffset + resultRun.characterCount);
251
+ const originalText = inputRun.content.substring(originalRun.charOffset, originalRun.charOffset + originalRun.numChars);
252
+ expect(resultText).to.equal(originalText);
253
+ }
254
+ }
255
+ }
256
+ });
257
+ it("adds margins", function () {
258
+ const expectMargins = (layoutRange, marginRange, margins) => {
259
+ expect(marginRange.low.x).to.equal(layoutRange.low.x - (margins.left ?? 0));
260
+ expect(marginRange.high.x).to.equal(layoutRange.high.x + (margins.right ?? 0));
261
+ expect(marginRange.low.y).to.equal(layoutRange.low.y - (margins.bottom ?? 0));
262
+ expect(marginRange.high.y).to.equal(layoutRange.high.y + (margins.top ?? 0));
263
+ };
264
+ const makeTextBlock = (margins) => {
265
+ const textBlock = TextBlock.create({ styleId: "", styleOverrides: { lineSpacingFactor: 0 }, margins });
266
+ textBlock.appendRun(makeTextRun("abc"));
267
+ textBlock.appendRun(makeTextRun("defg"));
268
+ return textBlock;
269
+ };
270
+ let block = makeTextBlock({});
271
+ let layout = doLayout(block);
272
+ // Margins should be 0 by default
273
+ expect(layout.range.isAlmostEqual(layout.textRange)).to.be.true;
274
+ expectMargins(layout.textRange, layout.range, {});
275
+ // All margins should be applied to the range
276
+ block = makeTextBlock({ left: 1, right: 2, top: 3, bottom: 4 });
277
+ layout = doLayout(block);
278
+ expectMargins(layout.textRange, layout.range, { left: 1, right: 2, top: 3, bottom: 4 });
279
+ // Just horizontal margins should be applied
280
+ block = makeTextBlock({ left: 1, right: 2 });
281
+ layout = doLayout(block);
282
+ expectMargins(layout.textRange, layout.range, { left: 1, right: 2 });
283
+ // Just vertical margins should be applied
284
+ block = makeTextBlock({ top: 1, bottom: 2 });
285
+ layout = doLayout(block);
286
+ expectMargins(layout.textRange, layout.range, { top: 1, bottom: 2 });
287
+ });
288
+ describe("range", () => {
289
+ it("aligns text to center based on height of stacked fraction", () => {
290
+ const textBlock = TextBlock.create({ styleId: "" });
291
+ const fractionRun = FractionRun.create({ numerator: "1", denominator: "2" });
292
+ const textRun = TextRun.create({ content: "text" });
293
+ textBlock.appendRun(fractionRun);
294
+ textBlock.appendRun(textRun);
295
+ const layout = doLayout(textBlock);
296
+ const fractionLayout = layout.lines[0].runs[0];
297
+ const textLayout = layout.lines[0].runs[1];
298
+ const round = (num, numDecimalPlaces) => {
299
+ const multiplier = Math.pow(100, numDecimalPlaces);
300
+ return Math.round(num * multiplier) / multiplier;
301
+ };
302
+ expect(textLayout.range.yLength()).to.equal(1);
303
+ expect(round(fractionLayout.range.yLength(), 2)).to.equal(1.75);
304
+ expect(fractionLayout.offsetFromLine.y).to.equal(0);
305
+ expect(round(textLayout.offsetFromLine.y, 3)).to.equal(.375);
306
+ });
307
+ it("produces one line per paragraph if document width <= 0", () => {
308
+ const textBlock = TextBlock.create({ styleId: "" });
309
+ for (let i = 0; i < 4; i++) {
310
+ const layout = doLayout(textBlock);
311
+ if (i === 0) {
312
+ expect(layout.range.isNull).to.be.true;
313
+ }
314
+ else {
315
+ expect(layout.lines.length).to.equal(i);
316
+ expect(layout.range.low.x).to.equal(0);
317
+ expect(layout.range.low.y).to.equal(-i - (0.5 * (i - 1))); // lineSpacingFactor=0.5
318
+ expect(layout.range.high.x).to.equal(i * 3);
319
+ expect(layout.range.high.y).to.equal(0);
320
+ }
321
+ for (let l = 0; l < layout.lines.length; l++) {
322
+ const line = layout.lines[l];
323
+ expect(line.runs.length).to.equal(l + 1);
324
+ expect(line.range.low.x).to.equal(0);
325
+ expect(line.range.low.y).to.equal(0);
326
+ expect(line.range.high.y).to.equal(1);
327
+ expect(line.range.high.x).to.equal(3 * (l + 1));
328
+ for (const run of line.runs) {
329
+ expect(run.charOffset).to.equal(0);
330
+ expect(run.numChars).to.equal(3);
331
+ expect(run.range.low.x).to.equal(0);
332
+ expect(run.range.low.y).to.equal(0);
333
+ expect(run.range.high.x).to.equal(3);
334
+ expect(run.range.high.y).to.equal(1);
335
+ }
336
+ }
337
+ const p = textBlock.appendParagraph();
338
+ for (let j = 0; j <= i; j++) {
339
+ p.runs.push(TextRun.create({ content: "Run" }));
340
+ }
341
+ }
342
+ });
343
+ it("produces a new line for each LineBreakRun", () => {
344
+ const lineSpacingFactor = 0.5;
345
+ const lineHeight = 1;
346
+ const textBlock = TextBlock.create({ styleId: "", styleOverrides: { lineSpacingFactor, lineHeight } });
347
+ textBlock.appendRun(TextRun.create({ content: "abc" }));
348
+ textBlock.appendRun(LineBreakRun.create());
349
+ textBlock.appendRun(TextRun.create({ content: "def" }));
350
+ textBlock.appendRun(TextRun.create({ content: "ghi" }));
351
+ textBlock.appendRun(LineBreakRun.create());
352
+ textBlock.appendRun(TextRun.create({ content: "jkl" }));
353
+ const tb = doLayout(textBlock);
354
+ expect(tb.lines.length).to.equal(3);
355
+ expect(tb.lines[0].runs.length).to.equal(2);
356
+ expect(tb.lines[1].runs.length).to.equal(3);
357
+ expect(tb.lines[2].runs.length).to.equal(1);
358
+ expect(tb.range.low.x).to.equal(0);
359
+ expect(tb.range.high.x).to.equal(6);
360
+ expect(tb.range.high.y).to.equal(0);
361
+ expect(tb.range.low.y).to.equal(-(lineSpacingFactor * 2 + lineHeight * 3));
362
+ });
363
+ it("applies tab shifts", () => {
364
+ const lineHeight = 1;
365
+ const tabInterval = 6;
366
+ const textBlock = TextBlock.create({ styleId: "", styleOverrides: { lineHeight, tabInterval } });
367
+ // Appends a line that looks like `stringOne` TAB `stringTwo` LINEBREAK
368
+ const appendLine = (stringOne, stringTwo, wantLineBreak = true) => {
369
+ if (stringOne.length > 0)
370
+ textBlock.appendRun(TextRun.create({ content: stringOne }));
371
+ textBlock.appendRun(TabRun.create({ styleOverrides: { tabInterval } }));
372
+ if (stringTwo.length > 0)
373
+ textBlock.appendRun(TextRun.create({ content: stringTwo }));
374
+ if (wantLineBreak)
375
+ textBlock.appendRun(LineBreakRun.create());
376
+ };
377
+ // The extra whitespace is intentional to show where the tab stops should be.
378
+ appendLine("", "a");
379
+ appendLine("", "bc");
380
+ appendLine("a", "a");
381
+ appendLine("bc", "bc");
382
+ appendLine("cde", "cde");
383
+ appendLine("cdefg", "cde"); // this one is the max tab distance before needing to move to the next tab stop
384
+ appendLine("cdefgh", "cde"); // This one should push to the next tab stop.
385
+ appendLine("cdefghi", "cde", false); // This one should push to the next tab stop.
386
+ const tb = doLayout(textBlock);
387
+ tb.lines.forEach((line, index) => {
388
+ const firstTextRun = (line.runs[0].source.type === "text") ? line.runs[0] : undefined;
389
+ const firstTabRun = (line.runs[0].source.type === "tab") ? line.runs[0] : line.runs[1];
390
+ const distance = (firstTextRun?.range.xLength() ?? 0) + firstTabRun.range.xLength();
391
+ const expectedDistance = ((firstTextRun?.range.xLength() || 0) >= tabInterval) ? tabInterval * 2 : tabInterval;
392
+ expect(distance).to.equal(expectedDistance, `Line ${index} does not have the expected tab distance. ${expectedDistance}`);
393
+ });
394
+ });
395
+ it("applies consecutive tab shifts", () => {
396
+ const lineHeight = 1;
397
+ const tabInterval = 6;
398
+ const textBlock = TextBlock.create({ styleId: "", styleOverrides: { lineHeight, tabInterval } });
399
+ // line 0: ----->----->----->LINEBREAK
400
+ textBlock.appendRun(TabRun.create({ styleOverrides: { tabInterval } }));
401
+ textBlock.appendRun(TabRun.create({ styleOverrides: { tabInterval } }));
402
+ textBlock.appendRun(TabRun.create({ styleOverrides: { tabInterval } }));
403
+ textBlock.appendRun(LineBreakRun.create());
404
+ // line 1: abc-->----->LINEBREAK
405
+ textBlock.appendRun(TextRun.create({ content: "abc" }));
406
+ textBlock.appendRun(TabRun.create({ styleOverrides: { tabInterval } }));
407
+ textBlock.appendRun(TabRun.create({ styleOverrides: { tabInterval } }));
408
+ textBlock.appendRun(LineBreakRun.create());
409
+ // line 2: abc--->->------>LINEBREAK
410
+ textBlock.appendRun(TextRun.create({ content: "abc" }));
411
+ textBlock.appendRun(TabRun.create({ styleOverrides: { tabInterval: 7 } }));
412
+ textBlock.appendRun(TabRun.create({ styleOverrides: { tabInterval: 2 } }));
413
+ textBlock.appendRun(TabRun.create({ styleOverrides: { tabInterval: 7 } }));
414
+ textBlock.appendRun(LineBreakRun.create());
415
+ // line 3: abc--->1/23->abcde->LINEBREAK
416
+ textBlock.appendRun(TextRun.create({ content: "abc" }));
417
+ textBlock.appendRun(TabRun.create({ styleOverrides: { tabInterval: 7 } }));
418
+ textBlock.appendRun(FractionRun.create({ numerator: "1", denominator: "23" }));
419
+ textBlock.appendRun(TabRun.create({ styleOverrides: { tabInterval: 3 } }));
420
+ textBlock.appendRun(TextRun.create({ content: "abcde" }));
421
+ textBlock.appendRun(TabRun.create({ styleOverrides: { tabInterval: 7 } }));
422
+ textBlock.appendRun(LineBreakRun.create());
423
+ const tb = doLayout(textBlock);
424
+ const line0 = tb.lines[0];
425
+ const line1 = tb.lines[1];
426
+ const line2 = tb.lines[2];
427
+ const line3 = tb.lines[3];
428
+ expect(line0.runs.length).to.equal(4);
429
+ expect(line0.range.xLength()).to.equal(3 * tabInterval, `Lines with only tabs should have the correct range length`);
430
+ expect(line1.runs.length).to.equal(4);
431
+ expect(line1.range.xLength()).to.equal(2 * tabInterval, `Tabs should be applied correctly when they are at the end of a line`);
432
+ expect(line2.runs.length).to.equal(5);
433
+ expect(line2.range.xLength()).to.equal(7 + 2 + 7, `Multiple tabs with different intervals should be applied correctly`);
434
+ expect(line3.runs.length).to.equal(7);
435
+ expect(line3.range.xLength()).to.equal(7 + 3 + 7, `Multiple tabs with different intervals should be applied correctly`);
436
+ });
437
+ it("computes ranges based on custom line spacing and line height", () => {
438
+ const lineSpacingFactor = 2;
439
+ const lineHeight = 3;
440
+ const textBlock = TextBlock.create({ styleId: "", styleOverrides: { lineSpacingFactor, lineHeight } });
441
+ textBlock.appendRun(TextRun.create({ content: "abc" }));
442
+ textBlock.appendRun(LineBreakRun.create());
443
+ textBlock.appendRun(TextRun.create({ content: "def" }));
444
+ textBlock.appendRun(TextRun.create({ content: "ghi" }));
445
+ textBlock.appendRun(LineBreakRun.create());
446
+ textBlock.appendRun(TextRun.create({ content: "jkl" }));
447
+ const tb = doLayout(textBlock);
448
+ expect(tb.lines.length).to.equal(3);
449
+ expect(tb.lines[0].runs.length).to.equal(2);
450
+ expect(tb.lines[1].runs.length).to.equal(3);
451
+ expect(tb.lines[2].runs.length).to.equal(1);
452
+ // We have 3 lines each `lineHeight` high, plus 2 line breaks in between each `lineHeight*lineSpacingFactor` high.
453
+ expect(tb.range.low.x).to.equal(0);
454
+ expect(tb.range.high.x).to.equal(6);
455
+ expect(tb.range.high.y).to.equal(0);
456
+ expect(tb.range.low.y).to.equal(-(lineHeight * 3 + (lineHeight * lineSpacingFactor) * 2));
457
+ expect(tb.lines[0].offsetFromDocument.y).to.equal(-lineHeight);
458
+ expect(tb.lines[1].offsetFromDocument.y).to.equal(tb.lines[0].offsetFromDocument.y - (lineHeight + lineHeight * lineSpacingFactor));
459
+ expect(tb.lines[2].offsetFromDocument.y).to.equal(tb.lines[1].offsetFromDocument.y - (lineHeight + lineHeight * lineSpacingFactor));
460
+ expect(tb.lines.every((line) => line.offsetFromDocument.x === 0)).to.be.true;
461
+ });
462
+ function expectRange(width, height, range) {
463
+ expect(range.xLength()).to.equal(width);
464
+ expect(range.yLength()).to.equal(height);
465
+ }
466
+ it("computes range for wrapped lines", function () {
467
+ if (!isIntlSupported()) {
468
+ this.skip();
469
+ }
470
+ const block = TextBlock.create({ styleId: "", width: 3, styleOverrides: { lineHeight: 1, lineSpacingFactor: 0 } });
471
+ function expectBlockRange(width, height) {
472
+ const layout = doLayout(block);
473
+ expectRange(width, height, layout.range);
474
+ }
475
+ block.appendRun(makeTextRun("abc"));
476
+ expectBlockRange(3, 1);
477
+ block.appendRun(makeTextRun("defg"));
478
+ expectBlockRange(4, 2);
479
+ block.width = 1;
480
+ expectBlockRange(4, 2);
481
+ block.width = 8;
482
+ expectBlockRange(8, 1);
483
+ block.width = 6;
484
+ expectBlockRange(6, 2);
485
+ block.width = 10;
486
+ expectBlockRange(10, 1);
487
+ block.appendRun(makeTextRun("hijk"));
488
+ expectBlockRange(10, 2);
489
+ });
490
+ it("computes range for split runs", function () {
491
+ if (!isIntlSupported()) {
492
+ this.skip();
493
+ }
494
+ const block = TextBlock.create({ styleId: "", styleOverrides: { lineHeight: 1, lineSpacingFactor: 0 } });
495
+ function expectBlockRange(width, height) {
496
+ const layout = doLayout(block);
497
+ expectRange(width, height, layout.range);
498
+ }
499
+ const sentence = "a bc def ghij klmno";
500
+ expect(sentence.length).to.equal(19);
501
+ block.appendRun(makeTextRun(sentence));
502
+ block.width = 19;
503
+ expectBlockRange(19, 1);
504
+ block.width = 10;
505
+ expectBlockRange(10, 2);
506
+ });
507
+ it("justifies lines", function () {
508
+ if (!isIntlSupported()) {
509
+ this.skip();
510
+ }
511
+ const block = TextBlock.create({ styleId: "", styleOverrides: { lineSpacingFactor: 0 } });
512
+ function expectBlockRange(width, height) {
513
+ const layout = doLayout(block);
514
+ expectRange(width, height, layout.range);
515
+ }
516
+ function expectLineOffset(offset, lineIndex) {
517
+ const layout = doLayout(block);
518
+ expect(layout.lines.length).least(lineIndex + 1);
519
+ const line = layout.lines[lineIndex];
520
+ expect(line.offsetFromDocument.y).to.equal(-(lineIndex + 1));
521
+ expect(line.offsetFromDocument.x).to.equal(offset);
522
+ }
523
+ // Two text runs with 7 characters total.
524
+ block.appendRun(makeTextRun("abc"));
525
+ block.appendRun(makeTextRun("defg"));
526
+ // 1 line of text with width 0: left, right, center justification.
527
+ block.justification = "left";
528
+ expectBlockRange(7, 1);
529
+ expectLineOffset(0, 0);
530
+ block.justification = "right";
531
+ expectBlockRange(7, 1);
532
+ expectLineOffset(0, 0);
533
+ block.justification = "center";
534
+ expectBlockRange(7, 1);
535
+ expectLineOffset(0, 0);
536
+ // 1 line of text from a width greater than number of characters: left, right, center justification.
537
+ block.width = 10;
538
+ block.justification = "left";
539
+ expectBlockRange(10, 1);
540
+ expectLineOffset(0, 0);
541
+ block.justification = "right";
542
+ expectBlockRange(10, 1);
543
+ expectLineOffset(3, 0); // 3 = 10 - 7
544
+ block.justification = "center";
545
+ expectBlockRange(10, 1);
546
+ expectLineOffset(1.5, 0); // 1.5 = (10 - 7) / 2
547
+ // 2 line of text from a width less than number of characters: left, right, center justification.
548
+ block.justification = "left";
549
+ block.width = 4;
550
+ expectBlockRange(4, 2);
551
+ expectLineOffset(0, 0);
552
+ expectLineOffset(0, 1);
553
+ block.justification = "right";
554
+ expectBlockRange(4, 2);
555
+ expectLineOffset(1, 0);
556
+ expectLineOffset(0, 1);
557
+ block.justification = "center";
558
+ expectBlockRange(4, 2);
559
+ expectLineOffset(0.5, 0);
560
+ expectLineOffset(0, 1);
561
+ // Testing text longer the the width of the text block.
562
+ block.width = 2;
563
+ block.justification = "left";
564
+ expectBlockRange(4, 2);
565
+ expectLineOffset(0, 0);
566
+ expectLineOffset(0, 1);
567
+ block.justification = "right";
568
+ expectBlockRange(4, 2);
569
+ expectLineOffset(-1, 0);
570
+ expectLineOffset(-2, 1);
571
+ block.appendRun(makeTextRun("123456789"));
572
+ expectBlockRange(9, 3);
573
+ expectLineOffset(-1, 0);
574
+ expectLineOffset(-2, 1);
575
+ expectLineOffset(-7, 2);
576
+ block.justification = "center";
577
+ expectBlockRange(9, 3);
578
+ expectLineOffset(-0.5, 0);
579
+ expectLineOffset(-1, 1);
580
+ expectLineOffset(-3.5, 2);
581
+ });
582
+ });
583
+ describe("word-wrapping", () => {
584
+ function expectLines(input, width, expectedLines) {
585
+ const textBlock = TextBlock.create({ styleId: "" });
586
+ textBlock.width = width;
587
+ const run = makeTextRun(input);
588
+ textBlock.appendRun(run);
589
+ const layout = doLayout(textBlock);
590
+ expect(layout.lines.every((line) => line.runs.every((r) => r.source === run))).to.be.true;
591
+ const actual = layout.lines.map((line) => line.runs.map((runLayout) => runLayout.source.content.substring(runLayout.charOffset, runLayout.charOffset + runLayout.numChars)).join(""));
592
+ expect(actual).to.deep.equal(expectedLines);
593
+ return layout;
594
+ }
595
+ it("splits paragraphs into multiple lines if runs exceed the document width", function () {
596
+ if (!isIntlSupported()) {
597
+ this.skip();
598
+ }
599
+ const textBlock = TextBlock.create({ styleId: "" });
600
+ textBlock.width = 6;
601
+ textBlock.appendRun(makeTextRun("ab"));
602
+ expect(doLayout(textBlock).lines.length).to.equal(1);
603
+ textBlock.appendRun(makeTextRun("cd"));
604
+ expect(doLayout(textBlock).lines.length).to.equal(1);
605
+ textBlock.appendRun(makeTextRun("ef"));
606
+ expect(doLayout(textBlock).lines.length).to.equal(1);
607
+ textBlock.appendRun(makeTextRun("ghi"));
608
+ expect(doLayout(textBlock).lines.length).to.equal(2);
609
+ textBlock.appendRun(makeTextRun("jklmnop"));
610
+ expect(doLayout(textBlock).lines.length).to.equal(3);
611
+ textBlock.appendRun(makeTextRun("q"));
612
+ expect(doLayout(textBlock).lines.length).to.equal(4);
613
+ textBlock.appendRun(makeTextRun("r"));
614
+ expect(doLayout(textBlock).lines.length).to.equal(4);
615
+ textBlock.appendRun(makeTextRun("stu"));
616
+ expect(doLayout(textBlock).lines.length).to.equal(4);
617
+ textBlock.appendRun(makeTextRun("vwxyz"));
618
+ expect(doLayout(textBlock).lines.length).to.equal(5);
619
+ });
620
+ it("splits a single TextRun at word boundaries if it exceeds the document width", function () {
621
+ if (!isIntlSupported()) {
622
+ this.skip();
623
+ }
624
+ expectLines("a bc def ghij klmno pqrstu vwxyz", 5, [
625
+ "a bc ",
626
+ "def ",
627
+ "ghij ",
628
+ "klmno ",
629
+ "pqrstu ",
630
+ "vwxyz",
631
+ ]);
632
+ const fox = "The quick brown fox jumped over the lazy dog";
633
+ expectLines(fox, 50, [fox]);
634
+ expectLines(fox, 40, [
635
+ // 1 2 3 4
636
+ // 34567890123456789012345678901234567890
637
+ "The quick brown fox jumped over the ",
638
+ "lazy dog",
639
+ ]);
640
+ expectLines(fox, 30, [
641
+ // 1 2 3
642
+ // 3456789012345678901234567890
643
+ "The quick brown fox jumped ",
644
+ "over the lazy dog",
645
+ ]);
646
+ expectLines(fox, 20, [
647
+ // 1 2
648
+ // 345678901234567890
649
+ "The quick brown fox ",
650
+ "jumped over the ",
651
+ "lazy dog",
652
+ ]);
653
+ expectLines(fox, 10, [
654
+ // 1
655
+ // 234567890
656
+ "The quick ",
657
+ "brown fox ",
658
+ "jumped ",
659
+ "over the ",
660
+ "lazy dog",
661
+ ]);
662
+ });
663
+ it("considers consecutive whitespace part of a single 'word'", function () {
664
+ if (!isIntlSupported()) {
665
+ this.skip();
666
+ }
667
+ expectLines("a b c d e f ", 3, [
668
+ "a ",
669
+ "b ",
670
+ "c ",
671
+ "d ",
672
+ "e ",
673
+ "f ",
674
+ ]);
675
+ });
676
+ it("wraps Japanese text", function () {
677
+ if (!isIntlSupported()) {
678
+ this.skip();
679
+ }
680
+ // "I am a cat. The name is Tanuki."
681
+ expectLines("吾輩は猫である。名前はたぬき。", 1, ["吾", "輩", "は", "猫", "で", "あ", "る。", "名", "前", "は", "た", "ぬ", "き。"]);
682
+ });
683
+ it("wraps tabs", function () {
684
+ if (!isIntlSupported()) {
685
+ this.skip();
686
+ }
687
+ const lineHeight = 1;
688
+ const textBlock = TextBlock.create({ styleId: "", styleOverrides: { lineHeight } });
689
+ // line 0: -->-->------> LINEBREAK
690
+ textBlock.appendRun(TabRun.create({ styleOverrides: { tabInterval: 3 } }));
691
+ textBlock.appendRun(TabRun.create({ styleOverrides: { tabInterval: 3 } }));
692
+ textBlock.appendRun(TabRun.create({ styleOverrides: { tabInterval: 7 } }));
693
+ textBlock.appendRun(LineBreakRun.create());
694
+ // line 1: a->b->cd-----> LINEBREAK
695
+ textBlock.appendRun(TextRun.create({ content: "a" }));
696
+ textBlock.appendRun(TabRun.create({ styleOverrides: { tabInterval: 3 } }));
697
+ textBlock.appendRun(TextRun.create({ content: "b" }));
698
+ textBlock.appendRun(TabRun.create({ styleOverrides: { tabInterval: 3 } }));
699
+ textBlock.appendRun(TextRun.create({ content: "cd" }));
700
+ textBlock.appendRun(TabRun.create({ styleOverrides: { tabInterval: 7 } }));
701
+ textBlock.appendRun(LineBreakRun.create());
702
+ // line 2: -->a->b------>cd LINEBREAK
703
+ textBlock.appendRun(TabRun.create({ styleOverrides: { tabInterval: 3 } }));
704
+ textBlock.appendRun(TextRun.create({ content: "a" }));
705
+ textBlock.appendRun(TabRun.create({ styleOverrides: { tabInterval: 3 } }));
706
+ textBlock.appendRun(TextRun.create({ content: "b" }));
707
+ textBlock.appendRun(TabRun.create({ styleOverrides: { tabInterval: 7 } }));
708
+ textBlock.appendRun(TextRun.create({ content: "cd" }));
709
+ textBlock.appendRun(LineBreakRun.create());
710
+ /* Full Width:
711
+ * -->-->------>
712
+ * a->b->cd---->
713
+ * -->a->b----->cd
714
+ */
715
+ let tb = doLayout(textBlock);
716
+ expect(tb.lines.length).to.equal(3, ``);
717
+ expect(tb.lines[0].range.xLength()).to.equal(13, ``);
718
+ expect(tb.lines[1].range.xLength()).to.equal(13, ``);
719
+ expect(tb.lines[2].range.xLength()).to.equal(15, ``);
720
+ /* Width of 10:
721
+ * -->-->
722
+ * ------>
723
+ * a->b->cd
724
+ * ------>
725
+ * -->a->b
726
+ * ------>cd
727
+ */
728
+ textBlock.width = 10;
729
+ tb = doLayout(textBlock);
730
+ expect(tb.lines.length).to.equal(6, ``);
731
+ expect(tb.lines[0].range.xLength()).to.equal(6, ``);
732
+ expect(tb.lines[1].range.xLength()).to.equal(7, ``);
733
+ expect(tb.lines[2].range.xLength()).to.equal(8, ``);
734
+ expect(tb.lines[3].range.xLength()).to.equal(7, ``);
735
+ expect(tb.lines[4].range.xLength()).to.equal(7, ``);
736
+ expect(tb.lines[5].range.xLength()).to.equal(9, ``);
737
+ });
738
+ it("performs word-wrapping with punctuation", function () {
739
+ if (!isIntlSupported()) {
740
+ this.skip();
741
+ }
742
+ expectLines("1.24 56.7 8,910", 1, ["1.24 ", "56.7 ", "8,910"]);
743
+ expectLines("a.bc de.f g,hij", 1, ["a.bc ", "de.f ", "g,hij"]);
744
+ expectLines("Let's see... can you (or anyone) predict?!", 1, [
745
+ "Let's ",
746
+ "see... ",
747
+ "can ",
748
+ "you ",
749
+ "(or ",
750
+ "anyone) ",
751
+ "predict?!",
752
+ ]);
753
+ });
754
+ it("performs word-wrapping and line-splitting with multiple runs", function () {
755
+ if (!isIntlSupported()) {
756
+ this.skip();
757
+ }
758
+ const textBlock = TextBlock.create({ styleId: "" });
759
+ for (const str of ["The ", "quick brown", " fox jumped over ", "the lazy ", "dog"]) {
760
+ textBlock.appendRun(makeTextRun(str));
761
+ }
762
+ function test(width, expected) {
763
+ textBlock.width = width;
764
+ const layout = doLayout(textBlock);
765
+ const actual = layout.lines.map((line) => line.runs.map((runLayout) => runLayout.source.content.substring(runLayout.charOffset, runLayout.charOffset + runLayout.numChars)).join(""));
766
+ expect(actual).to.deep.equal(expected);
767
+ }
768
+ test(50, ["The quick brown fox jumped over the lazy dog"]);
769
+ test(40, [
770
+ // 1 2 3 4
771
+ // 34567890123456789012345678901234567890
772
+ "The quick brown fox jumped over the ",
773
+ "lazy dog",
774
+ ]);
775
+ test(30, [
776
+ // 1 2 3
777
+ // 3456789012345678901234567890
778
+ "The quick brown fox jumped ",
779
+ "over the lazy dog",
780
+ ]);
781
+ test(20, [
782
+ // 1 2
783
+ // 345678901234567890
784
+ "The quick brown fox ",
785
+ "jumped over the ",
786
+ "lazy dog",
787
+ ]);
788
+ test(10, [
789
+ // 1
790
+ // 34567890
791
+ "The quick ",
792
+ "brown fox ",
793
+ "jumped ",
794
+ "over the ",
795
+ "lazy dog",
796
+ ]);
797
+ });
798
+ it("wraps multiple runs", function () {
799
+ if (!isIntlSupported()) {
800
+ this.skip();
801
+ }
802
+ const block = TextBlock.create({ styleId: "" });
803
+ block.appendRun(makeTextRun("aa")); // 2 chars wide
804
+ block.appendRun(makeTextRun("bb ccc d ee")); // 11 chars wide
805
+ block.appendRun(makeTextRun("ff ggg h")); // 8 chars wide
806
+ function expectLayout(width, expected) {
807
+ block.width = width;
808
+ const layout = doLayout(block);
809
+ expect(layout.stringify()).to.equal(expected);
810
+ }
811
+ expectLayout(23, "aabb ccc d eeff ggg h");
812
+ expectLayout(22, "aabb ccc d eeff ggg h");
813
+ expectLayout(21, "aabb ccc d eeff ggg h");
814
+ expectLayout(20, "aabb ccc d eeff ggg \nh");
815
+ expectLayout(19, "aabb ccc d eeff \nggg h");
816
+ expectLayout(18, "aabb ccc d eeff \nggg h");
817
+ expectLayout(17, "aabb ccc d eeff \nggg h");
818
+ expectLayout(16, "aabb ccc d eeff \nggg h");
819
+ expectLayout(15, "aabb ccc d ee\nff ggg h");
820
+ expectLayout(14, "aabb ccc d ee\nff ggg h");
821
+ expectLayout(13, "aabb ccc d ee\nff ggg h");
822
+ expectLayout(12, "aabb ccc d \neeff ggg h");
823
+ expectLayout(11, "aabb ccc d \neeff ggg h");
824
+ expectLayout(10, "aabb ccc \nd eeff \nggg h");
825
+ expectLayout(9, "aabb ccc \nd eeff \nggg h");
826
+ expectLayout(8, "aabb \nccc d ee\nff ggg h");
827
+ expectLayout(7, "aabb \nccc d \neeff \nggg h");
828
+ expectLayout(6, "aabb \nccc d \neeff \nggg h");
829
+ expectLayout(5, "aabb \nccc \nd ee\nff \nggg h");
830
+ expectLayout(4, "aa\nbb \nccc \nd ee\nff \nggg \nh");
831
+ expectLayout(3, "aa\nbb \nccc \nd \nee\nff \nggg \nh");
832
+ expectLayout(2, "aa\nbb \nccc \nd \nee\nff \nggg \nh");
833
+ expectLayout(1, "aa\nbb \nccc \nd \nee\nff \nggg \nh");
834
+ expectLayout(0, "aabb ccc d eeff ggg h");
835
+ expectLayout(-1, "aabb ccc d eeff ggg h");
836
+ expectLayout(-2, "aabb ccc d eeff ggg h");
837
+ });
838
+ it("does not word wrap due to floating point rounding error", function () {
839
+ if (!isIntlSupported()) {
840
+ this.skip();
841
+ }
842
+ const block = TextBlock.create({ styleId: "", styleOverrides: { lineHeight: 1, lineSpacingFactor: 0 } });
843
+ block.appendRun(makeTextRun("abc defg"));
844
+ const layout1 = doLayout(block);
845
+ let width = layout1.range.xLength();
846
+ // Simulate a floating point rounding error by slightly reducing the width
847
+ width -= Geometry.smallFloatingPoint;
848
+ block.width = width;
849
+ const layout2 = doLayout(block);
850
+ expect(layout2.range.yLength()).to.equal(1);
851
+ });
852
+ });
853
+ describe("grapheme offsets", () => {
854
+ function getLayoutResultAndStyleResolver(textBlock) {
855
+ const layout = doLayout(textBlock);
856
+ const result = layout.toResult();
857
+ const textStyleResolver = new TextStyleResolver({
858
+ textBlock,
859
+ iModel: {},
860
+ modelId: undefined,
861
+ findTextStyle: () => TextStyleSettings.defaults
862
+ });
863
+ return { textStyleResolver, result };
864
+ }
865
+ it("should return an empty array if source type is not text", function () {
866
+ const textBlock = TextBlock.create({ styleId: "" });
867
+ const fractionRun = FractionRun.create({ numerator: "1", denominator: "2" });
868
+ textBlock.appendRun(fractionRun);
869
+ const { textStyleResolver, result } = getLayoutResultAndStyleResolver(textBlock);
870
+ const args = {
871
+ textBlock,
872
+ iModel: {},
873
+ textStyleResolver,
874
+ findFontId: () => 0,
875
+ computeTextRange: computeTextRangeAsStringLength,
876
+ paragraphIndex: result.lines[0].sourceParagraphIndex,
877
+ runLayoutResult: result.lines[0].runs[0],
878
+ graphemeCharIndexes: [0],
879
+ };
880
+ const graphemeRanges = computeGraphemeOffsets(args);
881
+ expect(graphemeRanges).to.be.an("array").that.is.empty;
882
+ });
883
+ it("should handle empty text content", function () {
884
+ const textBlock = TextBlock.create({ styleId: "" });
885
+ const textRun = TextRun.create({ content: "" });
886
+ textBlock.appendRun(textRun);
887
+ const { textStyleResolver, result } = getLayoutResultAndStyleResolver(textBlock);
888
+ const args = {
889
+ textBlock,
890
+ iModel: {},
891
+ textStyleResolver,
892
+ findFontId: () => 0,
893
+ computeTextRange: computeTextRangeAsStringLength,
894
+ paragraphIndex: result.lines[0].sourceParagraphIndex,
895
+ runLayoutResult: result.lines[0].runs[0],
896
+ graphemeCharIndexes: [0], // Supply a grapheme index even though there is no text
897
+ };
898
+ const graphemeRanges = computeGraphemeOffsets(args);
899
+ expect(graphemeRanges).to.be.an("array").that.is.empty;
900
+ });
901
+ it("should compute grapheme offsets correctly for a given text", function () {
902
+ const textBlock = TextBlock.create({ styleId: "" });
903
+ const textRun = TextRun.create({ content: "hello" });
904
+ textBlock.appendRun(textRun);
905
+ const { textStyleResolver, result } = getLayoutResultAndStyleResolver(textBlock);
906
+ const args = {
907
+ textBlock,
908
+ iModel: {},
909
+ textStyleResolver,
910
+ findFontId: () => 0,
911
+ computeTextRange: computeTextRangeAsStringLength,
912
+ paragraphIndex: result.lines[0].sourceParagraphIndex,
913
+ runLayoutResult: result.lines[0].runs[0],
914
+ graphemeCharIndexes: [0, 1, 2, 3, 4],
915
+ };
916
+ const graphemeRanges = computeGraphemeOffsets(args);
917
+ expect(graphemeRanges).to.be.an("array").that.has.lengthOf(5);
918
+ expect(graphemeRanges[0].high.x).to.equal(1);
919
+ expect(graphemeRanges[4].high.x).to.equal(5);
920
+ });
921
+ it("should compute grapheme offsets correctly for non-English text", function () {
922
+ const textBlock = TextBlock.create({ styleId: "" });
923
+ // Hindi - "Paragraph"
924
+ const textRun = TextRun.create({ content: "अनुच्छेद" });
925
+ textBlock.appendRun(textRun);
926
+ const { textStyleResolver, result } = getLayoutResultAndStyleResolver(textBlock);
927
+ const args = {
928
+ textBlock,
929
+ iModel: {},
930
+ textStyleResolver,
931
+ findFontId: () => 0,
932
+ computeTextRange: computeTextRangeAsStringLength,
933
+ paragraphIndex: result.lines[0].sourceParagraphIndex,
934
+ runLayoutResult: result.lines[0].runs[0],
935
+ graphemeCharIndexes: [0, 1, 3, 7],
936
+ };
937
+ const graphemeRanges = computeGraphemeOffsets(args);
938
+ expect(graphemeRanges).to.be.an("array").that.has.lengthOf(4); // Length based on actual grapheme segmentation
939
+ expect(graphemeRanges[0].high.x).to.equal(1);
940
+ expect(graphemeRanges[1].high.x).to.equal(3);
941
+ expect(graphemeRanges[2].high.x).to.equal(7);
942
+ expect(graphemeRanges[3].high.x).to.equal(8);
943
+ });
944
+ it("should compute grapheme offsets correctly for emoji content", function () {
945
+ const textBlock = TextBlock.create({ styleId: "" });
946
+ const textRun = TextRun.create({ content: "👨‍👦" });
947
+ textBlock.appendRun(textRun);
948
+ const { textStyleResolver, result } = getLayoutResultAndStyleResolver(textBlock);
949
+ const args = {
950
+ textBlock,
951
+ iModel: {},
952
+ textStyleResolver,
953
+ findFontId: () => 0,
954
+ computeTextRange: computeTextRangeAsStringLength,
955
+ paragraphIndex: result.lines[0].sourceParagraphIndex,
956
+ runLayoutResult: result.lines[0].runs[0],
957
+ graphemeCharIndexes: [0],
958
+ };
959
+ const graphemeRanges = computeGraphemeOffsets(args);
960
+ expect(graphemeRanges).to.be.an("array").that.has.lengthOf(1); // Length based on actual grapheme segmentation
961
+ expect(graphemeRanges[0].high.x).to.equal(5);
962
+ });
963
+ });
964
+ describe("using native font library", () => {
965
+ let iModel;
966
+ before(() => {
967
+ const seedFileName = IModelTestUtils.resolveAssetFile("CompatibilityTestSeed.bim");
968
+ const testFileName = IModelTestUtils.prepareOutputFile("NativeFonts", "NativeFonts.bim");
969
+ iModel = IModelTestUtils.createSnapshotFromSeed(testFileName, seedFileName);
970
+ });
971
+ after(() => iModel.close());
972
+ it("maps font names to Id", async () => {
973
+ const vera = iModel.fonts.findId({ name: "Vera" });
974
+ expect(vera).to.equal(1);
975
+ const arial = await iModel.fonts.acquireId({ name: "Arial", type: FontType.TrueType });
976
+ const comic = await iModel.fonts.acquireId({ name: "Comic Sans", type: FontType.TrueType });
977
+ iModel.saveChanges();
978
+ expect(arial).to.equal(2);
979
+ expect(comic).to.equal(3);
980
+ expect(iModel.fonts.findId({ name: "Consolas" })).to.be.undefined;
981
+ function test(fontName, expectedFontId) {
982
+ const textBlock = TextBlock.create({ styleId: "" });
983
+ textBlock.appendRun(TextRun.create({ styleOverrides: { fontName } }));
984
+ const textStyleResolver = new TextStyleResolver({ textBlock, iModel });
985
+ const layout = layoutTextBlock({ textBlock, iModel, textStyleResolver });
986
+ const run = layout.lines[0].runs[0];
987
+ expect(run).not.to.be.undefined;
988
+ expect(run.fontId).to.equal(expectedFontId);
989
+ }
990
+ test("Arial", arial);
991
+ test("Comic Sans", comic);
992
+ test("Consolas", 0);
993
+ test("arial", arial);
994
+ test("aRIaL", arial);
995
+ });
996
+ function computeDimensions(args) {
997
+ const textBlock = TextBlock.create({
998
+ styleId: "",
999
+ styleOverrides: {
1000
+ lineHeight: args.height,
1001
+ widthFactor: args.width,
1002
+ },
1003
+ });
1004
+ textBlock.appendRun(TextRun.create({
1005
+ content: args.content ?? "This is a string of text.",
1006
+ styleOverrides: {
1007
+ isBold: args.bold,
1008
+ isItalic: args.italic,
1009
+ fontName: args.font ?? "Vera",
1010
+ },
1011
+ }));
1012
+ const textStyleResolver = new TextStyleResolver({ textBlock, iModel });
1013
+ const range = layoutTextBlock({ textBlock, iModel, textStyleResolver }).range;
1014
+ return { x: range.high.x - range.low.x, y: range.high.y - range.low.y };
1015
+ }
1016
+ it("computes different ranges for different strings", () => {
1017
+ expect(computeDimensions({ content: "text" })).to.deep.equal(computeDimensions({ content: "text" }));
1018
+ expect(computeDimensions({ content: "text" })).not.to.deep.equal(computeDimensions({ content: "texttexttext" }));
1019
+ expect(computeDimensions({ content: "text" })).not.to.deep.equal(computeDimensions({ content: "TEXT" }));
1020
+ });
1021
+ it("computes different ranges for different fonts", () => {
1022
+ // These two are embedded in the iModel.
1023
+ expect(computeDimensions({ font: "Vera" })).not.to.deep.equal(computeDimensions({ font: "Karla" }));
1024
+ // These two are not embedded in the iModel, but do exist in its font table - they should both fall back to the default font.
1025
+ expect(computeDimensions({ font: "Arial" })).to.deep.equal(computeDimensions({ font: "Comic Sans" }));
1026
+ });
1027
+ it("computes different ranges for different height and width", () => {
1028
+ expect(computeDimensions({ height: 2 })).to.deep.equal(computeDimensions({ height: 2 }));
1029
+ expect(computeDimensions({ height: 2 })).not.to.deep.equal(computeDimensions({ height: 3 }));
1030
+ expect(computeDimensions({ width: 2 })).to.deep.equal(computeDimensions({ width: 2 }));
1031
+ expect(computeDimensions({ width: 2 })).not.to.deep.equal(computeDimensions({ width: 3 }));
1032
+ });
1033
+ it("excludes trailing blank glyphs from justification ranges", () => {
1034
+ function computeRanges(chars) {
1035
+ return iModel.computeRangesForText({
1036
+ chars,
1037
+ bold: false,
1038
+ italic: false,
1039
+ fontId: 1,
1040
+ widthFactor: 1,
1041
+ lineHeight: 1,
1042
+ baselineShift: "none",
1043
+ });
1044
+ }
1045
+ function test(chars, expectEqualRanges) {
1046
+ const { justification, layout } = computeRanges(chars);
1047
+ expect(layout.low.x).to.equal(justification.low.x);
1048
+ expect(layout.high.y).to.equal(justification.high.y);
1049
+ expect(layout.low.y).to.equal(justification.low.y);
1050
+ if (expectEqualRanges) {
1051
+ expect(layout.high.x).to.equal(justification.high.x);
1052
+ }
1053
+ else {
1054
+ expect(layout.high.x).greaterThan(justification.high.x);
1055
+ }
1056
+ }
1057
+ test("abcdef", true);
1058
+ test("abcdef ", false);
1059
+ test("abcdef ", false);
1060
+ test("abc def", true);
1061
+ // new line has no width ever.
1062
+ test("abcdef\n", true);
1063
+ // apparently native code doesn't consider tab characters to be "blank".
1064
+ test("abcdef\t", true);
1065
+ // apparently native code doesn't consider "thin space" to be "blank".
1066
+ test("abcdef\u2009", true);
1067
+ const r1 = computeRanges("abcdef ");
1068
+ const r2 = computeRanges("abcdef ");
1069
+ expect(r1.layout.xLength()).lessThan(r2.layout.xLength());
1070
+ expect(r1.justification.xLength()).to.equal(r2.justification.xLength());
1071
+ });
1072
+ });
1073
+ });
1074
+ describe("produceTextBlockGeometry", () => {
1075
+ function makeText(color) {
1076
+ const styleOverrides = undefined !== color ? { color: color instanceof ColorDef ? color.toJSON() : color } : undefined;
1077
+ return TextRun.create({ styleOverrides, content: "text" });
1078
+ }
1079
+ function makeFraction(color) {
1080
+ const styleOverrides = undefined !== color ? { color: color instanceof ColorDef ? color.toJSON() : color } : undefined;
1081
+ return FractionRun.create({ numerator: "num", denominator: "denom", styleOverrides });
1082
+ }
1083
+ function makeBreak(color) {
1084
+ const styleOverrides = undefined !== color ? { color: color instanceof ColorDef ? color.toJSON() : color } : undefined;
1085
+ return LineBreakRun.create({ styleOverrides });
1086
+ }
1087
+ function makeTextBlock(runs) {
1088
+ const block = TextBlock.create({ styleId: "" });
1089
+ for (const run of runs) {
1090
+ block.appendRun(run);
1091
+ }
1092
+ return block;
1093
+ }
1094
+ function makeGeometry(runs) {
1095
+ const block = makeTextBlock(runs);
1096
+ const annotation = TextAnnotation.fromJSON({ textBlock: block.toJSON() });
1097
+ const layout = doLayout(block);
1098
+ return produceTextBlockGeometry(layout, annotation.computeTransform(layout.range)).entries;
1099
+ }
1100
+ it("produces an empty array for an empty text block", () => {
1101
+ expect(makeGeometry([])).to.deep.equal([]);
1102
+ });
1103
+ it("produces an empty array for a block consisting only of line breaks", () => {
1104
+ expect(makeGeometry([makeBreak(), makeBreak(), makeBreak()])).to.deep.equal([]);
1105
+ });
1106
+ it("produces one appearance entry if all runs use subcategory color", () => {
1107
+ const geom = makeGeometry([makeText(), makeFraction(), makeText("subcategory"), makeFraction("subcategory")]);
1108
+ expect(geom.length).to.equal(9);
1109
+ expect(geom[0].color).to.equal("subcategory");
1110
+ expect(geom.slice(1).some((entry) => entry.color !== undefined)).to.be.false;
1111
+ });
1112
+ it("produces strings and fraction separators", () => {
1113
+ const geom = makeGeometry([makeText(), makeFraction(), makeFraction(), makeText()]);
1114
+ expect(geom.length).to.equal(9);
1115
+ expect(geom[0].color).to.equal("subcategory");
1116
+ expect(geom[1].text).not.to.be.undefined;
1117
+ expect(geom[2].text).not.to.be.undefined;
1118
+ expect(geom[3].separator).not.to.be.undefined;
1119
+ expect(geom[4].text).not.to.be.undefined;
1120
+ expect(geom[5].text).not.to.be.undefined;
1121
+ expect(geom[6].separator).not.to.be.undefined;
1122
+ expect(geom[7].text).not.to.be.undefined;
1123
+ expect(geom[8].text).not.to.be.undefined;
1124
+ });
1125
+ it("produces an appearance change for each non-break run that is a different color from the previous run", () => {
1126
+ const geom = makeGeometry([
1127
+ makeText(ColorDef.blue),
1128
+ makeText(), // subcategory by default
1129
+ makeText(),
1130
+ makeText(ColorDef.red),
1131
+ makeText(ColorDef.white),
1132
+ makeText(ColorDef.white),
1133
+ makeBreak("subcategory"),
1134
+ makeFraction(ColorDef.green),
1135
+ makeText(ColorDef.green),
1136
+ makeBreak(ColorDef.black),
1137
+ makeText(ColorDef.green),
1138
+ ]).map((entry) => entry.text ? "text" : (entry.separator ? "sep" : (typeof entry.color === "number" ? ColorDef.fromJSON(entry.color) : entry.color)));
1139
+ expect(geom).to.deep.equal([
1140
+ ColorDef.blue,
1141
+ "text",
1142
+ "subcategory",
1143
+ "text",
1144
+ "text",
1145
+ ColorDef.red,
1146
+ "text",
1147
+ ColorDef.white,
1148
+ "text",
1149
+ "text",
1150
+ ColorDef.green,
1151
+ "text", "sep", "text",
1152
+ "text",
1153
+ "text",
1154
+ ]);
1155
+ });
1156
+ it("offsets geometry entries by margins", () => {
1157
+ function makeGeometryWithMargins(anchor, margins) {
1158
+ const runs = [makeText()];
1159
+ const block = makeTextBlock(runs);
1160
+ block.margins = margins;
1161
+ const annotation = TextAnnotation.fromJSON({ textBlock: block.toJSON() });
1162
+ annotation.anchor = anchor;
1163
+ const layout = doLayout(block);
1164
+ const geom = produceTextBlockGeometry(layout, annotation.computeTransform(layout.range)).entries;
1165
+ return geom[1].text;
1166
+ }
1167
+ function testMargins(margins, height, width) {
1168
+ // We want to disregard negative margins. Note, I'm not changing the margins object itself. It gets passed into makeGeometryWithMargins as it is.
1169
+ const left = margins.left >= 0 ? margins.left : 0;
1170
+ const right = margins.right >= 0 ? margins.right : 0;
1171
+ const top = margins.top >= 0 ? margins.top : 0;
1172
+ const bottom = margins.bottom >= 0 ? margins.bottom : 0;
1173
+ // Test case: bottom, left
1174
+ let props = makeGeometryWithMargins({ horizontal: "left", vertical: "bottom" }, margins);
1175
+ expect(props).not.to.be.undefined;
1176
+ expect(props?.origin, "Expected geometry to be offset by left and bottom margins").to.deep.equal({ x: left, y: bottom, z: 0 });
1177
+ // Test case: top, right
1178
+ props = makeGeometryWithMargins({ vertical: "top", horizontal: "right" }, margins);
1179
+ let x = (right + width) * -1;
1180
+ let y = (top + height) * -1;
1181
+ expect(props).not.to.be.undefined;
1182
+ expect(props?.origin, "Expected geometry to be offset by top and right margins").to.deep.equal({ x, y, z: 0 });
1183
+ // Test case: middle, center
1184
+ props = makeGeometryWithMargins({ vertical: "middle", horizontal: "center" }, margins);
1185
+ x = (left - right - width) / 2;
1186
+ y = (bottom - top - height) / 2;
1187
+ expect(props).not.to.be.undefined;
1188
+ expect(props?.origin, "Expected geometry to be centered in the margins").to.deep.equal({ x, y, z: 0 });
1189
+ }
1190
+ // xLength will be 4 because of the mock implementation on line 16.
1191
+ // yLength will be 1 because of the mock implementation on line 16.
1192
+ testMargins({ top: 0, right: 0, bottom: 0, left: 0 }, 1, 4);
1193
+ testMargins({ top: 1, right: 2, bottom: 3, left: 4 }, 1, 4);
1194
+ testMargins({ top: -1, right: -2, bottom: -3, left: -4 }, 1, 4);
1195
+ });
1196
+ });
1197
+ // Ignoring the text strings from the spell checker
1198
+ // cspell:ignore jklmnop vwxyz defg hijk ghij klmno pqrstu Tanuki aabb eeff nggg amet adipiscing elit Phasellus pretium malesuada venenatis eleifend Donec sapien Nullam commodo accumsan lacinia metus enim pharetra lacus facilisis Duis suscipit quis feugiat fermentum ut augue Mauris iaculis odio rhoncus lorem viverra turpis elementum posuere Consolas अनुच्छेद cdefg cdefgh cdefghi
1199
+ //# sourceMappingURL=TextBlock.test.js.map