@363045841yyt/klinechart-core 0.9.0-alpha.0 → 0.9.0-alpha.2

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (372) hide show
  1. package/dist/controllers/createChartController.d.ts.map +1 -1
  2. package/dist/controllers/createChartController.js +31 -13
  3. package/dist/controllers/createChartController.js.map +1 -1
  4. package/dist/controllers/index.d.ts +1 -0
  5. package/dist/controllers/index.d.ts.map +1 -1
  6. package/dist/controllers/index.js.map +1 -1
  7. package/dist/controllers/types.d.ts +12 -0
  8. package/dist/controllers/types.d.ts.map +1 -1
  9. package/dist/engine/chart.d.ts +29 -11
  10. package/dist/engine/chart.d.ts.map +1 -1
  11. package/dist/engine/chart.js +147 -25
  12. package/dist/engine/chart.js.map +1 -1
  13. package/dist/engine/controller/interaction.d.ts +29 -4
  14. package/dist/engine/controller/interaction.d.ts.map +1 -1
  15. package/dist/engine/controller/interaction.js +78 -31
  16. package/dist/engine/controller/interaction.js.map +1 -1
  17. package/dist/engine/data/incrementalLoadHint.d.ts.map +1 -1
  18. package/dist/engine/data/incrementalLoadHint.js +5 -1
  19. package/dist/engine/data/incrementalLoadHint.js.map +1 -1
  20. package/dist/engine/drawing/DrawingState.d.ts +19 -34
  21. package/dist/engine/drawing/DrawingState.d.ts.map +1 -1
  22. package/dist/engine/drawing/DrawingState.js +110 -92
  23. package/dist/engine/drawing/DrawingState.js.map +1 -1
  24. package/dist/engine/drawing/index.d.ts +4 -1
  25. package/dist/engine/drawing/index.d.ts.map +1 -1
  26. package/dist/engine/drawing/index.js +9 -4
  27. package/dist/engine/drawing/index.js.map +1 -1
  28. package/dist/engine/drawing/interaction.d.ts +9 -29
  29. package/dist/engine/drawing/interaction.d.ts.map +1 -1
  30. package/dist/engine/drawing/interaction.js +23 -40
  31. package/dist/engine/drawing/interaction.js.map +1 -1
  32. package/dist/engine/indicators/chartIndicatorManager.d.ts.map +1 -1
  33. package/dist/engine/indicators/chartIndicatorManager.js +4 -12
  34. package/dist/engine/indicators/chartIndicatorManager.js.map +1 -1
  35. package/dist/engine/layout/chartPaneLayout.d.ts +0 -2
  36. package/dist/engine/layout/chartPaneLayout.d.ts.map +1 -1
  37. package/dist/engine/layout/chartPaneLayout.js +5 -9
  38. package/dist/engine/layout/chartPaneLayout.js.map +1 -1
  39. package/dist/engine/layout/pane.d.ts +0 -39
  40. package/dist/engine/layout/pane.d.ts.map +1 -1
  41. package/dist/engine/layout/pane.js +0 -9
  42. package/dist/engine/layout/pane.js.map +1 -1
  43. package/dist/engine/paneRenderer.d.ts +1 -10
  44. package/dist/engine/paneRenderer.d.ts.map +1 -1
  45. package/dist/engine/paneRenderer.js +2 -19
  46. package/dist/engine/paneRenderer.js.map +1 -1
  47. package/dist/engine/render/chartRenderer.d.ts +49 -8
  48. package/dist/engine/render/chartRenderer.d.ts.map +1 -1
  49. package/dist/engine/render/chartRenderer.js +143 -72
  50. package/dist/engine/render/chartRenderer.js.map +1 -1
  51. package/dist/engine/renderers/Indicator/atr.js +3 -13
  52. package/dist/engine/renderers/Indicator/atr.js.map +1 -1
  53. package/dist/engine/renderers/Indicator/boll.d.ts.map +1 -1
  54. package/dist/engine/renderers/Indicator/boll.js +12 -24
  55. package/dist/engine/renderers/Indicator/boll.js.map +1 -1
  56. package/dist/engine/renderers/Indicator/cci.js +6 -13
  57. package/dist/engine/renderers/Indicator/cci.js.map +1 -1
  58. package/dist/engine/renderers/Indicator/chaikinVol.js +3 -11
  59. package/dist/engine/renderers/Indicator/chaikinVol.js.map +1 -1
  60. package/dist/engine/renderers/Indicator/cmf.js +3 -11
  61. package/dist/engine/renderers/Indicator/cmf.js.map +1 -1
  62. package/dist/engine/renderers/Indicator/dema.js +3 -11
  63. package/dist/engine/renderers/Indicator/dema.js.map +1 -1
  64. package/dist/engine/renderers/Indicator/donchian.js +3 -11
  65. package/dist/engine/renderers/Indicator/donchian.js.map +1 -1
  66. package/dist/engine/renderers/Indicator/ene.d.ts.map +1 -1
  67. package/dist/engine/renderers/Indicator/ene.js +12 -24
  68. package/dist/engine/renderers/Indicator/ene.js.map +1 -1
  69. package/dist/engine/renderers/Indicator/expma.d.ts.map +1 -1
  70. package/dist/engine/renderers/Indicator/expma.js +5 -11
  71. package/dist/engine/renderers/Indicator/expma.js.map +1 -1
  72. package/dist/engine/renderers/Indicator/fastk.js +6 -13
  73. package/dist/engine/renderers/Indicator/fastk.js.map +1 -1
  74. package/dist/engine/renderers/Indicator/fib.js +3 -11
  75. package/dist/engine/renderers/Indicator/fib.js.map +1 -1
  76. package/dist/engine/renderers/Indicator/hma.js +3 -11
  77. package/dist/engine/renderers/Indicator/hma.js.map +1 -1
  78. package/dist/engine/renderers/Indicator/hv.js +3 -11
  79. package/dist/engine/renderers/Indicator/hv.js.map +1 -1
  80. package/dist/engine/renderers/Indicator/ichimoku.js +24 -18
  81. package/dist/engine/renderers/Indicator/ichimoku.js.map +1 -1
  82. package/dist/engine/renderers/Indicator/kama.js +3 -11
  83. package/dist/engine/renderers/Indicator/kama.js.map +1 -1
  84. package/dist/engine/renderers/Indicator/keltner.js +3 -11
  85. package/dist/engine/renderers/Indicator/keltner.js.map +1 -1
  86. package/dist/engine/renderers/Indicator/kst.js +9 -17
  87. package/dist/engine/renderers/Indicator/kst.js.map +1 -1
  88. package/dist/engine/renderers/Indicator/ma.d.ts.map +1 -1
  89. package/dist/engine/renderers/Indicator/ma.js +10 -21
  90. package/dist/engine/renderers/Indicator/ma.js.map +1 -1
  91. package/dist/engine/renderers/Indicator/macd.js +14 -44
  92. package/dist/engine/renderers/Indicator/macd.js.map +1 -1
  93. package/dist/engine/renderers/Indicator/mfi.js +3 -11
  94. package/dist/engine/renderers/Indicator/mfi.js.map +1 -1
  95. package/dist/engine/renderers/Indicator/mom.js +6 -13
  96. package/dist/engine/renderers/Indicator/mom.js.map +1 -1
  97. package/dist/engine/renderers/Indicator/obv.js +3 -11
  98. package/dist/engine/renderers/Indicator/obv.js.map +1 -1
  99. package/dist/engine/renderers/Indicator/parkinson.js +3 -11
  100. package/dist/engine/renderers/Indicator/parkinson.js.map +1 -1
  101. package/dist/engine/renderers/Indicator/pvt.js +3 -11
  102. package/dist/engine/renderers/Indicator/pvt.js.map +1 -1
  103. package/dist/engine/renderers/Indicator/roc.js +3 -11
  104. package/dist/engine/renderers/Indicator/roc.js.map +1 -1
  105. package/dist/engine/renderers/Indicator/rsi.js +12 -20
  106. package/dist/engine/renderers/Indicator/rsi.js.map +1 -1
  107. package/dist/engine/renderers/Indicator/shared/webglBand.d.ts +0 -2
  108. package/dist/engine/renderers/Indicator/shared/webglBand.d.ts.map +1 -1
  109. package/dist/engine/renderers/Indicator/shared/webglBand.js +0 -6
  110. package/dist/engine/renderers/Indicator/shared/webglBand.js.map +1 -1
  111. package/dist/engine/renderers/Indicator/stoch.js +9 -17
  112. package/dist/engine/renderers/Indicator/stoch.js.map +1 -1
  113. package/dist/engine/renderers/Indicator/tema.js +3 -11
  114. package/dist/engine/renderers/Indicator/tema.js.map +1 -1
  115. package/dist/engine/renderers/Indicator/trix.js +3 -11
  116. package/dist/engine/renderers/Indicator/trix.js.map +1 -1
  117. package/dist/engine/renderers/Indicator/vma.js +3 -11
  118. package/dist/engine/renderers/Indicator/vma.js.map +1 -1
  119. package/dist/engine/renderers/Indicator/vwap.js +3 -11
  120. package/dist/engine/renderers/Indicator/vwap.js.map +1 -1
  121. package/dist/engine/renderers/Indicator/wma.js +3 -11
  122. package/dist/engine/renderers/Indicator/wma.js.map +1 -1
  123. package/dist/engine/renderers/Indicator/wmsr.js +6 -13
  124. package/dist/engine/renderers/Indicator/wmsr.js.map +1 -1
  125. package/dist/engine/renderers/candle.d.ts.map +1 -1
  126. package/dist/engine/renderers/candle.js +21 -28
  127. package/dist/engine/renderers/candle.js.map +1 -1
  128. package/dist/engine/renderers/candleViaRenderer.d.ts +19 -0
  129. package/dist/engine/renderers/candleViaRenderer.d.ts.map +1 -0
  130. package/dist/engine/renderers/candleViaRenderer.js +15 -0
  131. package/dist/engine/renderers/candleViaRenderer.js.map +1 -0
  132. package/dist/engine/renderers/linesViaRenderer.d.ts +55 -0
  133. package/dist/engine/renderers/linesViaRenderer.d.ts.map +1 -0
  134. package/dist/engine/renderers/linesViaRenderer.js +169 -0
  135. package/dist/engine/renderers/linesViaRenderer.js.map +1 -0
  136. package/dist/engine/renderers/rectsViaRenderer.d.ts +18 -0
  137. package/dist/engine/renderers/rectsViaRenderer.d.ts.map +1 -0
  138. package/dist/engine/renderers/rectsViaRenderer.js +63 -0
  139. package/dist/engine/renderers/rectsViaRenderer.js.map +1 -0
  140. package/dist/engine/renderers/subVolume.js +7 -26
  141. package/dist/engine/renderers/subVolume.js.map +1 -1
  142. package/dist/engine/renderers/timeAxis.js +1 -1
  143. package/dist/engine/renderers/timeAxis.js.map +1 -1
  144. package/dist/engine/state/chartStateKernel.d.ts +11 -2
  145. package/dist/engine/state/chartStateKernel.d.ts.map +1 -1
  146. package/dist/engine/state/chartStateKernel.js +28 -12
  147. package/dist/engine/state/chartStateKernel.js.map +1 -1
  148. package/dist/engine/state/index.d.ts +1 -1
  149. package/dist/engine/state/index.d.ts.map +1 -1
  150. package/dist/engine/state/index.js +1 -1
  151. package/dist/engine/state/index.js.map +1 -1
  152. package/dist/engine/state/interactionState.d.ts +15 -7
  153. package/dist/engine/state/interactionState.d.ts.map +1 -1
  154. package/dist/engine/state/interactionState.js +55 -60
  155. package/dist/engine/state/interactionState.js.map +1 -1
  156. package/dist/engine/state/rendererState.d.ts +14 -0
  157. package/dist/engine/state/rendererState.d.ts.map +1 -0
  158. package/dist/engine/state/rendererState.js +25 -0
  159. package/dist/engine/state/rendererState.js.map +1 -0
  160. package/dist/engine/state/themeState.d.ts +11 -4
  161. package/dist/engine/state/themeState.d.ts.map +1 -1
  162. package/dist/engine/state/themeState.js +13 -5
  163. package/dist/engine/state/themeState.js.map +1 -1
  164. package/dist/engine/state/viewportState.d.ts.map +1 -1
  165. package/dist/engine/state/viewportState.js +7 -3
  166. package/dist/engine/state/viewportState.js.map +1 -1
  167. package/dist/engine/subPaneManager.d.ts.map +1 -1
  168. package/dist/engine/subPaneManager.js +2 -10
  169. package/dist/engine/subPaneManager.js.map +1 -1
  170. package/dist/foundation/config/chartSettings.d.ts +16 -4
  171. package/dist/foundation/config/chartSettings.d.ts.map +1 -1
  172. package/dist/foundation/config/chartSettings.js +21 -6
  173. package/dist/foundation/config/chartSettings.js.map +1 -1
  174. package/dist/foundation/plugin/index.d.ts +0 -1
  175. package/dist/foundation/plugin/index.d.ts.map +1 -1
  176. package/dist/foundation/plugin/rendererPluginManager.d.ts +1 -22
  177. package/dist/foundation/plugin/rendererPluginManager.d.ts.map +1 -1
  178. package/dist/foundation/plugin/rendererPluginManager.js +0 -84
  179. package/dist/foundation/plugin/rendererPluginManager.js.map +1 -1
  180. package/dist/foundation/plugin/types.d.ts +11 -17
  181. package/dist/foundation/plugin/types.d.ts.map +1 -1
  182. package/dist/foundation/plugin/types.js.map +1 -1
  183. package/dist/foundation/reactivity/frameTransaction.d.ts +71 -0
  184. package/dist/foundation/reactivity/frameTransaction.d.ts.map +1 -0
  185. package/dist/foundation/reactivity/frameTransaction.js +170 -0
  186. package/dist/foundation/reactivity/frameTransaction.js.map +1 -0
  187. package/dist/foundation/reactivity/index.d.ts +4 -2
  188. package/dist/foundation/reactivity/index.d.ts.map +1 -1
  189. package/dist/foundation/reactivity/index.js +2 -1
  190. package/dist/foundation/reactivity/index.js.map +1 -1
  191. package/dist/foundation/reactivity/signal.d.ts +20 -0
  192. package/dist/foundation/reactivity/signal.d.ts.map +1 -1
  193. package/dist/foundation/reactivity/signal.js +27 -0
  194. package/dist/foundation/reactivity/signal.js.map +1 -1
  195. package/dist/foundation/tokens/theme-dark.d.ts.map +1 -1
  196. package/dist/foundation/tokens/theme-dark.js +2 -1
  197. package/dist/foundation/tokens/theme-dark.js.map +1 -1
  198. package/dist/foundation/tokens/theme-light.d.ts.map +1 -1
  199. package/dist/foundation/tokens/theme-light.js +2 -1
  200. package/dist/foundation/tokens/theme-light.js.map +1 -1
  201. package/dist/rendering/render/Renderer.d.ts +29 -14
  202. package/dist/rendering/render/Renderer.d.ts.map +1 -1
  203. package/dist/rendering/render/Renderer.js +3 -10
  204. package/dist/rendering/render/Renderer.js.map +1 -1
  205. package/dist/rendering/render/SurfaceBackend.d.ts +5 -7
  206. package/dist/rendering/render/SurfaceBackend.d.ts.map +1 -1
  207. package/dist/rendering/render/SurfaceBackend.js +5 -7
  208. package/dist/rendering/render/SurfaceBackend.js.map +1 -1
  209. package/dist/rendering/render/createCanvas2DRenderer.d.ts +3 -0
  210. package/dist/rendering/render/createCanvas2DRenderer.d.ts.map +1 -0
  211. package/dist/rendering/render/createCanvas2DRenderer.js +74 -0
  212. package/dist/rendering/render/createCanvas2DRenderer.js.map +1 -0
  213. package/dist/rendering/render/createDefaultRendererHost.d.ts +4 -0
  214. package/dist/rendering/render/createDefaultRendererHost.d.ts.map +1 -0
  215. package/dist/rendering/render/createDefaultRendererHost.js +54 -0
  216. package/dist/rendering/render/createDefaultRendererHost.js.map +1 -0
  217. package/dist/rendering/render/createWebGLRenderer.d.ts.map +1 -1
  218. package/dist/rendering/render/createWebGLRenderer.js +42 -80
  219. package/dist/rendering/render/createWebGLRenderer.js.map +1 -1
  220. package/dist/rendering/render/createWebGPURenderer.d.ts +11 -0
  221. package/dist/rendering/render/createWebGPURenderer.d.ts.map +1 -0
  222. package/dist/rendering/render/createWebGPURenderer.js +619 -0
  223. package/dist/rendering/render/createWebGPURenderer.js.map +1 -0
  224. package/dist/rendering/render/createWebGPUSurfaceBackend.d.ts +15 -0
  225. package/dist/rendering/render/createWebGPUSurfaceBackend.d.ts.map +1 -0
  226. package/dist/rendering/render/createWebGPUSurfaceBackend.js +92 -0
  227. package/dist/rendering/render/createWebGPUSurfaceBackend.js.map +1 -0
  228. package/dist/rendering/render/frameMetrics.d.ts +19 -0
  229. package/dist/rendering/render/frameMetrics.d.ts.map +1 -0
  230. package/dist/rendering/render/frameMetrics.js +43 -0
  231. package/dist/rendering/render/frameMetrics.js.map +1 -0
  232. package/dist/rendering/render/index.d.ts +10 -0
  233. package/dist/rendering/render/index.d.ts.map +1 -1
  234. package/dist/rendering/render/index.js +6 -0
  235. package/dist/rendering/render/index.js.map +1 -1
  236. package/dist/rendering/render/rendererHost.d.ts +34 -0
  237. package/dist/rendering/render/rendererHost.d.ts.map +1 -0
  238. package/dist/rendering/render/rendererHost.js +144 -0
  239. package/dist/rendering/render/rendererHost.js.map +1 -0
  240. package/dist/rendering/render/webgpuResourceTable.d.ts +25 -0
  241. package/dist/rendering/render/webgpuResourceTable.d.ts.map +1 -0
  242. package/dist/rendering/render/webgpuResourceTable.js +54 -0
  243. package/dist/rendering/render/webgpuResourceTable.js.map +1 -0
  244. package/dist/rendering/scene/createLayerFromPlugin.d.ts.map +1 -1
  245. package/dist/rendering/scene/createLayerFromPlugin.js +10 -2
  246. package/dist/rendering/scene/createLayerFromPlugin.js.map +1 -1
  247. package/dist/rendering/scene/layerRegistry.d.ts +3 -5
  248. package/dist/rendering/scene/layerRegistry.d.ts.map +1 -1
  249. package/dist/rendering/scene/layerRegistry.js +1 -1
  250. package/dist/rendering/scene/layerRegistry.js.map +1 -1
  251. package/dist/rendering/scene/retainedScene.d.ts +60 -0
  252. package/dist/rendering/scene/retainedScene.d.ts.map +1 -0
  253. package/dist/rendering/scene/retainedScene.js +42 -0
  254. package/dist/rendering/scene/retainedScene.js.map +1 -0
  255. package/dist/version.d.ts +1 -1
  256. package/dist/version.js +1 -1
  257. package/package.json +2 -1
  258. package/src/__tests__/signal.test.ts +47 -1
  259. package/src/controllers/__tests__/createChartController.theme.test.ts +102 -0
  260. package/src/controllers/createChartController.ts +36 -12
  261. package/src/controllers/index.ts +5 -0
  262. package/src/controllers/types.ts +14 -0
  263. package/src/engine/__tests__/chart.dpr.test.ts +64 -0
  264. package/src/engine/__tests__/paneRenderer.resize.test.ts +0 -7
  265. package/src/engine/__tests__/renderSinglePath.test.ts +121 -0
  266. package/src/engine/chart.ts +172 -25
  267. package/src/engine/controller/__tests__/interaction.dpr.test.ts +45 -41
  268. package/src/engine/controller/interaction.ts +81 -30
  269. package/src/engine/data/__tests__/chartDataManager.incrementalLoad.test.ts +1 -0
  270. package/src/engine/data/incrementalLoadHint.ts +6 -1
  271. package/src/engine/drawing/DrawingState.ts +107 -89
  272. package/src/engine/drawing/__tests__/drawingState.workCopy.test.ts +95 -36
  273. package/src/engine/drawing/__tests__/drawingStore.projection.test.ts +22 -0
  274. package/src/engine/drawing/index.ts +12 -4
  275. package/src/engine/drawing/interaction.ts +25 -40
  276. package/src/engine/indicators/chartIndicatorManager.ts +6 -16
  277. package/src/engine/layout/chartPaneLayout.ts +6 -11
  278. package/src/engine/layout/pane.ts +0 -44
  279. package/src/engine/paneRenderer.ts +3 -34
  280. package/src/engine/render/chartRenderer.ts +181 -81
  281. package/src/engine/renderers/Indicator/atr.ts +5 -17
  282. package/src/engine/renderers/Indicator/boll.ts +15 -26
  283. package/src/engine/renderers/Indicator/cci.ts +7 -17
  284. package/src/engine/renderers/Indicator/chaikinVol.ts +3 -15
  285. package/src/engine/renderers/Indicator/cmf.ts +3 -15
  286. package/src/engine/renderers/Indicator/dema.ts +3 -15
  287. package/src/engine/renderers/Indicator/donchian.ts +3 -12
  288. package/src/engine/renderers/Indicator/ene.ts +15 -25
  289. package/src/engine/renderers/Indicator/expma.ts +4 -13
  290. package/src/engine/renderers/Indicator/fastk.ts +7 -17
  291. package/src/engine/renderers/Indicator/fib.ts +3 -12
  292. package/src/engine/renderers/Indicator/hma.ts +3 -15
  293. package/src/engine/renderers/Indicator/hv.ts +3 -15
  294. package/src/engine/renderers/Indicator/ichimoku.ts +21 -24
  295. package/src/engine/renderers/Indicator/kama.ts +3 -15
  296. package/src/engine/renderers/Indicator/keltner.ts +3 -12
  297. package/src/engine/renderers/Indicator/kst.ts +9 -20
  298. package/src/engine/renderers/Indicator/ma.ts +9 -21
  299. package/src/engine/renderers/Indicator/macd.ts +27 -102
  300. package/src/engine/renderers/Indicator/mfi.ts +3 -15
  301. package/src/engine/renderers/Indicator/mom.ts +7 -17
  302. package/src/engine/renderers/Indicator/obv.ts +3 -15
  303. package/src/engine/renderers/Indicator/parkinson.ts +3 -15
  304. package/src/engine/renderers/Indicator/pvt.ts +3 -15
  305. package/src/engine/renderers/Indicator/roc.ts +3 -15
  306. package/src/engine/renderers/Indicator/rsi.ts +12 -23
  307. package/src/engine/renderers/Indicator/shared/webglBand.ts +0 -13
  308. package/src/engine/renderers/Indicator/stoch.ts +9 -20
  309. package/src/engine/renderers/Indicator/tema.ts +3 -15
  310. package/src/engine/renderers/Indicator/trix.ts +3 -12
  311. package/src/engine/renderers/Indicator/vma.ts +3 -15
  312. package/src/engine/renderers/Indicator/vwap.ts +3 -15
  313. package/src/engine/renderers/Indicator/wma.ts +3 -15
  314. package/src/engine/renderers/Indicator/wmsr.ts +7 -17
  315. package/src/engine/renderers/__tests__/candle.sceneRenderer.test.ts +208 -0
  316. package/src/engine/renderers/__tests__/candleViaRenderer.test.ts +100 -0
  317. package/src/engine/renderers/__tests__/linesViaRenderer.test.ts +263 -0
  318. package/src/engine/renderers/__tests__/rectsViaRenderer.test.ts +87 -0
  319. package/src/engine/renderers/candle.ts +26 -69
  320. package/src/engine/renderers/candleViaRenderer.ts +38 -0
  321. package/src/engine/renderers/linesViaRenderer.ts +226 -0
  322. package/src/engine/renderers/rectsViaRenderer.ts +83 -0
  323. package/src/engine/renderers/subVolume.ts +9 -61
  324. package/src/engine/renderers/timeAxis.ts +1 -1
  325. package/src/engine/state/__tests__/effectiveTheme.test.ts +49 -0
  326. package/src/engine/state/__tests__/rendererState.test.ts +36 -0
  327. package/src/engine/state/__tests__/settingsState.test.ts +1 -1
  328. package/src/engine/state/chartStateKernel.ts +38 -17
  329. package/src/engine/state/index.ts +6 -1
  330. package/src/engine/state/interactionState.ts +73 -102
  331. package/src/engine/state/rendererState.ts +32 -0
  332. package/src/engine/state/themeState.ts +15 -8
  333. package/src/engine/state/viewportState.ts +6 -3
  334. package/src/engine/subPaneManager.ts +2 -16
  335. package/src/foundation/config/__tests__/chartSettings.test.ts +25 -0
  336. package/src/foundation/config/chartSettings.ts +24 -7
  337. package/src/foundation/plugin/index.ts +0 -1
  338. package/src/foundation/plugin/rendererPluginManager.ts +0 -99
  339. package/src/foundation/plugin/types.ts +11 -18
  340. package/src/foundation/reactivity/__tests__/frameTransaction.test.ts +306 -0
  341. package/src/foundation/reactivity/frameTransaction.ts +239 -0
  342. package/src/foundation/reactivity/index.ts +8 -0
  343. package/src/foundation/reactivity/signal.ts +39 -0
  344. package/src/foundation/tokens/__tests__/__snapshots__/baseline.test.ts.snap +2 -2
  345. package/src/foundation/tokens/theme-dark.ts +2 -1
  346. package/src/foundation/tokens/theme-light.ts +2 -1
  347. package/src/rendering/render/Renderer.ts +27 -14
  348. package/src/rendering/render/SurfaceBackend.ts +5 -7
  349. package/src/rendering/render/__tests__/canvas2DRenderer.test.ts +34 -0
  350. package/src/rendering/render/__tests__/contract.test.ts +2 -2
  351. package/src/rendering/render/__tests__/frameMetrics.test.ts +24 -0
  352. package/src/rendering/render/__tests__/rendererHost.test.ts +157 -0
  353. package/src/rendering/render/__tests__/webglRenderer.fallback.test.ts +14 -74
  354. package/src/rendering/render/__tests__/webglRenderer.test.ts +64 -6
  355. package/src/rendering/render/__tests__/webgpuRenderer.test.ts +370 -0
  356. package/src/rendering/render/__tests__/webgpuResourceTable.test.ts +62 -0
  357. package/src/rendering/render/__tests__/webgpuSurfaceBackend.test.ts +120 -0
  358. package/src/rendering/render/createCanvas2DRenderer.ts +83 -0
  359. package/src/rendering/render/createDefaultRendererHost.ts +74 -0
  360. package/src/rendering/render/createWebGLRenderer.ts +41 -87
  361. package/src/rendering/render/createWebGPURenderer.ts +677 -0
  362. package/src/rendering/render/createWebGPUSurfaceBackend.ts +106 -0
  363. package/src/rendering/render/frameMetrics.ts +54 -0
  364. package/src/rendering/render/index.ts +30 -0
  365. package/src/rendering/render/rendererHost.ts +210 -0
  366. package/src/rendering/render/webgpuResourceTable.ts +87 -0
  367. package/src/rendering/scene/__tests__/layerFromPlugin.test.ts +29 -2
  368. package/src/rendering/scene/__tests__/retainedScene.test.ts +59 -0
  369. package/src/rendering/scene/createLayerFromPlugin.ts +9 -2
  370. package/src/rendering/scene/layerRegistry.ts +4 -6
  371. package/src/rendering/scene/retainedScene.ts +101 -0
  372. package/src/version.ts +1 -1
@@ -15,6 +15,7 @@ import { createCCIVisibleStateComposer } from '../../indicators/visibleStateComp
15
15
 
16
16
  import { createCciScaleRendererPlugin } from './scale/cci_scale'
17
17
  import { createSingleLineTitleInfo } from './shared/titleInfo'
18
+ import { tryDrawLinesGpu } from '../linesViaRenderer'
18
19
 
19
20
  type LinePoint = { x: number; y: number }
20
21
 
@@ -100,7 +101,7 @@ function createCCIRendererPlugin(options: CCIRendererOptions = {}): RendererPlug
100
101
  },
101
102
 
102
103
  draw(context: RenderContext) {
103
- const { ctx, pane, range, scrollLeft, dpr, kLineCenters, lineWebGLSurface } = context
104
+ const { ctx, pane, range, scrollLeft, dpr, kLineCenters } = context
104
105
  const colors = resolveThemeColors(
105
106
  context.theme,
106
107
  context.isAsiaMarket,
@@ -185,22 +186,11 @@ function createCCIRendererPlugin(options: CCIRendererOptions = {}): RendererPlug
185
186
  }
186
187
 
187
188
  // 绘制 CCI 线(WebGL 优先,Canvas2D 回退)
188
- const enableWebGL = context.settings?.enableWebGLRendering !== false
189
- let usedWebGL = false
190
- if (enableWebGL && lineWebGLSurface?.isAvailable()) {
191
- if (params.showCCI && cachedCCIPoints.length >= 2) {
192
- const ok = lineWebGLSurface.drawLineStrips(
193
- [{ points: cachedCCIPoints, width: 1, color: colors.cci.cci }],
194
- scrollLeft,
195
- )
196
- if (ok) {
197
- usedWebGL = true
198
- lineWebGLSurface.compositeTo(ctx, { imageSmoothingEnabled: false })
199
- }
200
- }
201
- }
202
-
203
- if (!usedWebGL) {
189
+ const cciLines =
190
+ params.showCCI && cachedCCIPoints.length >= 2
191
+ ? [{ points: cachedCCIPoints, width: 1, color: colors.cci.cci }]
192
+ : []
193
+ if (!tryDrawLinesGpu(context, cciLines, scrollLeft)) {
204
194
  drawCCILineWithCanvas2D(ctx, scrollLeft, cachedCCIPoints, params, colors)
205
195
  }
206
196
  },
@@ -14,6 +14,7 @@ import {
14
14
  EMPTY_CHAIKIN_VOL_STATE,
15
15
  } from '../../indicators/state/chaikinVolState'
16
16
  import { createSparseVisibleStateComposer } from '../../indicators/visibleStateComposers'
17
+ import { tryDrawLinesGpu } from '../linesViaRenderer'
17
18
 
18
19
  import { createSingleLineTitleInfo } from './shared/titleInfo'
19
20
 
@@ -60,7 +61,7 @@ function createChaikinVolRendererPlugin(options: { paneId?: string } = {}): Rend
60
61
  return key ? [key] : []
61
62
  },
62
63
  draw(context: RenderContext) {
63
- const { ctx, pane, range, scrollLeft, kLineCenters, lineWebGLSurface } = context
64
+ const { ctx, pane, range, scrollLeft, kLineCenters } = context
64
65
  const stateKey = resolveKey()
65
66
  if (!stateKey) return
66
67
  const state = pluginHost?.getSharedState<ChaikinVolRenderState>(stateKey)
@@ -101,20 +102,7 @@ function createChaikinVolRendererPlugin(options: { paneId?: string } = {}): Rend
101
102
 
102
103
  if (points.length < 2) return
103
104
 
104
- const enableWebGL = context.settings?.enableWebGLRendering !== false
105
- let usedWebGL = false
106
- if (enableWebGL && lineWebGLSurface?.isAvailable()) {
107
- const allOk = lineWebGLSurface.drawLineStrips(
108
- [{ points, width: 1, color: CHAIKIN_VOL_COLOR }],
109
- scrollLeft,
110
- )
111
- if (allOk) {
112
- usedWebGL = true
113
- lineWebGLSurface.compositeTo(ctx, { imageSmoothingEnabled: false })
114
- }
115
- }
116
-
117
- if (usedWebGL) return
105
+ if (tryDrawLinesGpu(context, [{ points, width: 1, color: CHAIKIN_VOL_COLOR }], scrollLeft)) return
118
106
 
119
107
  ctx.save()
120
108
  ctx.translate(-scrollLeft, 0)
@@ -11,6 +11,7 @@ import type { IndicatorScheduler, CMFSchedulerConfig } from '../../indicators/sc
11
11
  import type { CMFRenderState } from '../../indicators/state/cmfState'
12
12
  import { createCMFStateKey, EMPTY_CMF_STATE } from '../../indicators/state/cmfState'
13
13
  import { createFixedRangeSparseVisibleStateComposer } from '../../indicators/visibleStateComposers'
14
+ import { tryDrawLinesGpu } from '../linesViaRenderer'
14
15
 
15
16
  import { createSingleLineTitleInfo } from './shared/titleInfo'
16
17
 
@@ -54,7 +55,7 @@ function createCMFRendererPlugin(options: { paneId?: string } = {}): RendererPlu
54
55
  return key ? [key] : []
55
56
  },
56
57
  draw(context: RenderContext) {
57
- const { ctx, pane, range, scrollLeft, kLineCenters, lineWebGLSurface } = context
58
+ const { ctx, pane, range, scrollLeft, kLineCenters } = context
58
59
  const stateKey = resolveKey()
59
60
  if (!stateKey) return
60
61
  const state = pluginHost?.getSharedState<CMFRenderState>(stateKey)
@@ -95,20 +96,7 @@ function createCMFRendererPlugin(options: { paneId?: string } = {}): RendererPlu
95
96
 
96
97
  if (points.length < 2) return
97
98
 
98
- const enableWebGL = context.settings?.enableWebGLRendering !== false
99
- let usedWebGL = false
100
- if (enableWebGL && lineWebGLSurface?.isAvailable()) {
101
- const allOk = lineWebGLSurface.drawLineStrips(
102
- [{ points, width: 1, color: CMF_COLOR }],
103
- scrollLeft,
104
- )
105
- if (allOk) {
106
- usedWebGL = true
107
- lineWebGLSurface.compositeTo(ctx, { imageSmoothingEnabled: false })
108
- }
109
- }
110
-
111
- if (usedWebGL) return
99
+ if (tryDrawLinesGpu(context, [{ points, width: 1, color: CMF_COLOR }], scrollLeft)) return
112
100
 
113
101
  ctx.save()
114
102
  ctx.translate(-scrollLeft, 0)
@@ -11,6 +11,7 @@ import type { IndicatorScheduler, DEMASchedulerConfig } from '../../indicators/s
11
11
  import type { DEMARenderState } from '../../indicators/state/demaState'
12
12
  import { createDEMAStateKey, EMPTY_DEMA_STATE } from '../../indicators/state/demaState'
13
13
  import { createSparseVisibleStateComposer } from '../../indicators/visibleStateComposers'
14
+ import { tryDrawLinesGpu } from '../linesViaRenderer'
14
15
 
15
16
  import { createSingleLineTitleInfo } from './shared/titleInfo'
16
17
 
@@ -62,7 +63,7 @@ function createDEMARendererPlugin(options: DEMARendererOptions = {}): RendererPl
62
63
  },
63
64
 
64
65
  draw(context: RenderContext) {
65
- const { ctx, pane, range, scrollLeft, kLineCenters, lineWebGLSurface } = context
66
+ const { ctx, pane, range, scrollLeft, kLineCenters } = context
66
67
 
67
68
  const stateKey = resolveKey()
68
69
  if (!stateKey) return
@@ -84,20 +85,7 @@ function createDEMARendererPlugin(options: DEMARendererOptions = {}): RendererPl
84
85
 
85
86
  if (points.length < 2) return
86
87
 
87
- const enableWebGL = context.settings?.enableWebGLRendering !== false
88
- let usedWebGL = false
89
- if (enableWebGL && lineWebGLSurface?.isAvailable()) {
90
- const allOk = lineWebGLSurface.drawLineStrips(
91
- [{ points, width: 1, color: DEMA_COLOR }],
92
- scrollLeft,
93
- )
94
- if (allOk) {
95
- usedWebGL = true
96
- lineWebGLSurface.compositeTo(ctx, { imageSmoothingEnabled: false })
97
- }
98
- }
99
-
100
- if (usedWebGL) return
88
+ if (tryDrawLinesGpu(context, [{ points, width: 1, color: DEMA_COLOR }], scrollLeft)) return
101
89
 
102
90
  ctx.save()
103
91
  ctx.translate(-scrollLeft, 0)
@@ -16,6 +16,7 @@ import type { IndicatorScheduler, DonchianSchedulerConfig } from '../../indicato
16
16
  import type { DonchianRenderState } from '../../indicators/state/donchianState'
17
17
  import { createDonchianStateKey, EMPTY_DONCHIAN_STATE } from '../../indicators/state/donchianState'
18
18
  import { createBandVisibleStateComposer } from '../../indicators/visibleStateComposers'
19
+ import { tryDrawLinesGpu } from '../linesViaRenderer'
19
20
 
20
21
  const DONCHIAN_UPPER_COLOR = '#0891b2'
21
22
  const DONCHIAN_MIDDLE_COLOR = '#94a3b8'
@@ -68,7 +69,7 @@ function createDonchianRendererPlugin(
68
69
  },
69
70
 
70
71
  draw(context: RenderContext) {
71
- const { ctx, pane, range, scrollLeft, kLineCenters, lineWebGLSurface } = context
72
+ const { ctx, pane, range, scrollLeft, kLineCenters } = context
72
73
  const stateKey = resolveKey()
73
74
  if (!stateKey) return
74
75
  const state = pluginHost?.getSharedState<DonchianRenderState>(stateKey)
@@ -102,17 +103,7 @@ function createDonchianRendererPlugin(
102
103
  if (lowerPts.length >= 2)
103
104
  lines.push({ points: lowerPts, width: 1, color: DONCHIAN_LOWER_COLOR })
104
105
 
105
- const enableWebGL = context.settings?.enableWebGLRendering !== false
106
- let usedWebGL = false
107
- if (enableWebGL && lineWebGLSurface?.isAvailable()) {
108
- const allOk = lines.length > 0 && lineWebGLSurface.drawLineStrips(lines, scrollLeft)
109
- if (allOk) {
110
- usedWebGL = true
111
- lineWebGLSurface.compositeTo(ctx, { imageSmoothingEnabled: false })
112
- }
113
- }
114
-
115
- if (usedWebGL) return
106
+ if (tryDrawLinesGpu(context, lines, scrollLeft)) return
116
107
 
117
108
  ctx.save()
118
109
  ctx.translate(-scrollLeft, 0)
@@ -20,10 +20,14 @@ import type {
20
20
  import type { ENESchedulerConfig, IndicatorScheduler } from '../../indicators/scheduler'
21
21
  import { ENE_STATE_KEY, type ENERenderState } from '../../indicators/state/eneState'
22
22
 
23
- import { getRgbaAlpha, toOpaqueRgba, compositeLineSurface } from './shared/webglBand'
23
+ import { getRgbaAlpha, toOpaqueRgba } from './shared/webglBand'
24
+ import { tryDrawFilledBandGpu, tryDrawLinesGpu } from '../linesViaRenderer'
24
25
 
25
26
  type LinePoint = { x: number; y: number }
26
27
 
28
+ /**
29
+ * ENE GPU:先 band fill 再上/中/下轨。仅 sceneRenderer;失败返回 false 走 2D。
30
+ */
27
31
  function drawENEWithWebGL(
28
32
  context: RenderContext,
29
33
  data: {
@@ -37,25 +41,18 @@ function drawENEWithWebGL(
37
41
  context.isAsiaMarket,
38
42
  context.colorPresetSettings,
39
43
  )
40
- if (context.settings?.enableWebGLRendering === false) return false
41
- const surface = context.lineWebGLSurface
42
- if (!surface || !surface.isAvailable()) return false
43
-
44
- surface.clear()
45
-
46
- let allOk = true
44
+ // band 默认 false:无 surface 时不得假成功跳过 2D
45
+ let bandOk = false
47
46
  if (data.upperPoints.length >= 2 && data.lowerPoints.length >= 2) {
48
- surface.clear()
49
- allOk = surface.drawFilledBand(
50
- { upperPoints: data.upperPoints, lowerPoints: data.lowerPoints },
47
+ bandOk = tryDrawFilledBandGpu(
48
+ context,
49
+ data.upperPoints,
50
+ data.lowerPoints,
51
51
  toOpaqueRgba(colors.ene.bandFill),
52
52
  context.scrollLeft,
53
+ getRgbaAlpha(colors.ene.bandFill),
53
54
  )
54
- if (allOk) {
55
- compositeLineSurface(context, surface, getRgbaAlpha(colors.ene.bandFill))
56
- }
57
55
  }
58
- surface.clear()
59
56
 
60
57
  const lineStrips: Array<{ points: LinePoint[]; width: number; color: string }> = []
61
58
  if (data.upperPoints.length >= 2) {
@@ -67,17 +64,10 @@ function drawENEWithWebGL(
67
64
  if (data.lowerPoints.length >= 2) {
68
65
  lineStrips.push({ points: data.lowerPoints, width: 1, color: colors.ene.lower })
69
66
  }
70
- if (lineStrips.length > 0) {
71
- allOk = surface.drawLineStrips(lineStrips, context.scrollLeft)
72
- }
73
- if (!allOk) {
74
- surface.clear()
75
- return false
76
- }
77
67
 
78
- compositeLineSurface(context, surface)
79
- surface.clear()
80
- return true
68
+ if (lineStrips.length === 0) return bandOk
69
+ // 线失败 → false,整图 2D 重画(含 band)
70
+ return tryDrawLinesGpu(context, lineStrips, context.scrollLeft)
81
71
  }
82
72
 
83
73
  /** 创建 ENE(轨道线)渲染器插件(无状态版本)
@@ -19,6 +19,7 @@ import type {
19
19
  } from '../../indicators/indicatorMetadata'
20
20
  import type { EXPMASchedulerConfig, IndicatorScheduler } from '../../indicators/scheduler'
21
21
  import { EXPMA_STATE_KEY, type EXPMARenderState } from '../../indicators/state/expmaState'
22
+ import { tryDrawLinesGpu } from '../linesViaRenderer'
22
23
 
23
24
  type LinePoint = { x: number; y: number }
24
25
 
@@ -127,7 +128,7 @@ export function createEXPMARendererPlugin(): RendererPluginWithHost {
127
128
  },
128
129
 
129
130
  draw(context: RenderContext) {
130
- const { ctx, pane, data, range, scrollLeft, dpr, kLineCenters, lineWebGLSurface } = context
131
+ const { ctx, pane, data, range, scrollLeft, dpr, kLineCenters } = context
131
132
  const klineData = data as KLineData[]
132
133
  const colors = resolveThemeColors(
133
134
  context.theme,
@@ -169,9 +170,7 @@ export function createEXPMARendererPlugin(): RendererPluginWithHost {
169
170
  }
170
171
  }
171
172
 
172
- const enableWebGL = context.settings?.enableWebGLRendering !== false
173
- let usedWebGL = false
174
- if (enableWebGL && lineWebGLSurface?.isAvailable()) {
173
+ {
175
174
  const lines: Array<{ points: LinePoint[]; width: number; color: string }> = []
176
175
  if (cachedFastPoints.length >= 2) {
177
176
  lines.push({ points: cachedFastPoints, width: 1, color: colors.expma.fast })
@@ -179,17 +178,9 @@ export function createEXPMARendererPlugin(): RendererPluginWithHost {
179
178
  if (cachedSlowPoints.length >= 2) {
180
179
  lines.push({ points: cachedSlowPoints, width: 1, color: colors.expma.slow })
181
180
  }
182
-
183
- const allOk = lines.length > 0 && lineWebGLSurface.drawLineStrips(lines, scrollLeft)
184
-
185
- if (allOk) {
186
- usedWebGL = true
187
- lineWebGLSurface.compositeTo(ctx, { imageSmoothingEnabled: false })
188
- }
181
+ if (tryDrawLinesGpu(context, lines, scrollLeft)) return
189
182
  }
190
183
 
191
- if (usedWebGL) return
192
-
193
184
  ctx.save()
194
185
  ctx.translate(-scrollLeft, 0)
195
186
  ctx.lineWidth = 1
@@ -16,6 +16,7 @@ import { createFixedRangeSparseVisibleStateComposer } from '../../indicators/vis
16
16
  import { createFastkScaleRendererPlugin } from './scale/fastk_scale'
17
17
  import { createDashedLineRenderer } from './shared/dashedLines'
18
18
  import { createSingleLineTitleInfo } from './shared/titleInfo'
19
+ import { tryDrawLinesGpu } from '../linesViaRenderer'
19
20
 
20
21
  type LinePoint = { x: number; y: number }
21
22
 
@@ -104,7 +105,7 @@ function createFASTKRendererPlugin(options: FASTKRendererOptions = {}): Renderer
104
105
  },
105
106
 
106
107
  draw(context: RenderContext) {
107
- const { ctx, pane, range, scrollLeft, dpr, kLineCenters, lineWebGLSurface } = context
108
+ const { ctx, pane, range, scrollLeft, dpr, kLineCenters } = context
108
109
  const colors = resolveThemeColors(
109
110
  context.theme,
110
111
  context.isAsiaMarket,
@@ -161,22 +162,11 @@ function createFASTKRendererPlugin(options: FASTKRendererOptions = {}): Renderer
161
162
  }
162
163
 
163
164
  // 绘制 FASTK 线(WebGL 优先,Canvas2D 回退)
164
- const enableWebGL = context.settings?.enableWebGLRendering !== false
165
- let usedWebGL = false
166
- if (enableWebGL && lineWebGLSurface?.isAvailable()) {
167
- if (params.showFASTK && cachedFASTKPoints.length >= 2) {
168
- const ok = lineWebGLSurface.drawLineStrips(
169
- [{ points: cachedFASTKPoints, width: 1, color: colors.kdj.k }],
170
- scrollLeft,
171
- )
172
- if (ok) {
173
- usedWebGL = true
174
- lineWebGLSurface.compositeTo(ctx, { imageSmoothingEnabled: false })
175
- }
176
- }
177
- }
178
-
179
- if (!usedWebGL) {
165
+ const fastkLines =
166
+ params.showFASTK && cachedFASTKPoints.length >= 2
167
+ ? [{ points: cachedFASTKPoints, width: 1, color: colors.kdj.k }]
168
+ : []
169
+ if (!tryDrawLinesGpu(context, fastkLines, scrollLeft)) {
180
170
  drawFASTKLineWithCanvas2D(ctx, scrollLeft, cachedFASTKPoints, params, colors)
181
171
  }
182
172
  },
@@ -16,6 +16,7 @@ import type { IndicatorScheduler, FibSchedulerConfig } from '../../indicators/sc
16
16
  import type { FibRenderState } from '../../indicators/state/fibState'
17
17
  import { createFibStateKey, EMPTY_FIB_STATE } from '../../indicators/state/fibState'
18
18
  import { createExactRangePointVisibleStateComposer } from '../../indicators/visibleStateComposers'
19
+ import { tryDrawLinesGpu } from '../linesViaRenderer'
19
20
 
20
21
  const FIB_COLORS = {
21
22
  high: '#94a3b8',
@@ -66,7 +67,7 @@ function createFibRendererPlugin(options: { paneId?: string } = {}): RendererPlu
66
67
  return key ? [key] : []
67
68
  },
68
69
  draw(context: RenderContext) {
69
- const { ctx, pane, range, scrollLeft, kLineCenters, lineWebGLSurface } = context
70
+ const { ctx, pane, range, scrollLeft, kLineCenters } = context
70
71
  const stateKey = resolveKey()
71
72
  if (!stateKey) return
72
73
  const state = pluginHost?.getSharedState<FibRenderState>(stateKey)
@@ -107,17 +108,7 @@ function createFibRendererPlugin(options: { paneId?: string } = {}): RendererPlu
107
108
  }
108
109
  }
109
110
 
110
- const enableWebGL = context.settings?.enableWebGLRendering !== false
111
- let usedWebGL = false
112
- if (enableWebGL && lineWebGLSurface?.isAvailable()) {
113
- const allOk = lines.length > 0 && lineWebGLSurface.drawLineStrips(lines, scrollLeft)
114
- if (allOk) {
115
- usedWebGL = true
116
- lineWebGLSurface.compositeTo(ctx, { imageSmoothingEnabled: false })
117
- }
118
- }
119
-
120
- if (usedWebGL) return
111
+ if (tryDrawLinesGpu(context, lines, scrollLeft)) return
121
112
 
122
113
  ctx.save()
123
114
  ctx.translate(-scrollLeft, 0)
@@ -11,6 +11,7 @@ import type { IndicatorScheduler, HMASchedulerConfig } from '../../indicators/sc
11
11
  import type { HMARenderState } from '../../indicators/state/hmaState'
12
12
  import { createHMAStateKey, EMPTY_HMA_STATE } from '../../indicators/state/hmaState'
13
13
  import { createSparseVisibleStateComposer } from '../../indicators/visibleStateComposers'
14
+ import { tryDrawLinesGpu } from '../linesViaRenderer'
14
15
 
15
16
  import { createSingleLineTitleInfo } from './shared/titleInfo'
16
17
 
@@ -62,7 +63,7 @@ function createHMARendererPlugin(options: HMARendererOptions = {}): RendererPlug
62
63
  },
63
64
 
64
65
  draw(context: RenderContext) {
65
- const { ctx, pane, range, scrollLeft, kLineCenters, lineWebGLSurface } = context
66
+ const { ctx, pane, range, scrollLeft, kLineCenters } = context
66
67
 
67
68
  const stateKey = resolveKey()
68
69
  if (!stateKey) return
@@ -84,20 +85,7 @@ function createHMARendererPlugin(options: HMARendererOptions = {}): RendererPlug
84
85
 
85
86
  if (points.length < 2) return
86
87
 
87
- const enableWebGL = context.settings?.enableWebGLRendering !== false
88
- let usedWebGL = false
89
- if (enableWebGL && lineWebGLSurface?.isAvailable()) {
90
- const allOk = lineWebGLSurface.drawLineStrips(
91
- [{ points, width: 1, color: HMA_COLOR }],
92
- scrollLeft,
93
- )
94
- if (allOk) {
95
- usedWebGL = true
96
- lineWebGLSurface.compositeTo(ctx, { imageSmoothingEnabled: false })
97
- }
98
- }
99
-
100
- if (usedWebGL) return
88
+ if (tryDrawLinesGpu(context, [{ points, width: 1, color: HMA_COLOR }], scrollLeft)) return
101
89
 
102
90
  ctx.save()
103
91
  ctx.translate(-scrollLeft, 0)
@@ -13,6 +13,7 @@ import type { HVRenderState } from '../../indicators/state/hvState'
13
13
  import { createHVStateKey } from '../../indicators/state/hvState'
14
14
  import { EMPTY_HV_STATE } from '../../indicators/state/hvState'
15
15
  import { createNonNegativeSparseVisibleStateComposer } from '../../indicators/visibleStateComposers'
16
+ import { tryDrawLinesGpu } from '../linesViaRenderer'
16
17
 
17
18
  import { createSingleLineTitleInfo } from './shared/titleInfo'
18
19
 
@@ -57,7 +58,7 @@ function createHVRendererPlugin(options: { paneId?: string } = {}): RendererPlug
57
58
  return key ? [key] : []
58
59
  },
59
60
  draw(context: RenderContext) {
60
- const { ctx, pane, range, scrollLeft, kLineCenters, lineWebGLSurface } = context
61
+ const { ctx, pane, range, scrollLeft, kLineCenters } = context
61
62
  const stateKey = resolveKey()
62
63
  if (!stateKey) return
63
64
  const state = pluginHost?.getSharedState<HVRenderState>(stateKey)
@@ -84,20 +85,7 @@ function createHVRendererPlugin(options: { paneId?: string } = {}): RendererPlug
84
85
 
85
86
  if (points.length < 2) return
86
87
 
87
- const enableWebGL = context.settings?.enableWebGLRendering !== false
88
- let usedWebGL = false
89
- if (enableWebGL && lineWebGLSurface?.isAvailable()) {
90
- const allOk = lineWebGLSurface.drawLineStrips(
91
- [{ points, width: 1, color: HV_COLOR }],
92
- scrollLeft,
93
- )
94
- if (allOk) {
95
- usedWebGL = true
96
- lineWebGLSurface.compositeTo(ctx, { imageSmoothingEnabled: false })
97
- }
98
- }
99
-
100
- if (usedWebGL) return
88
+ if (tryDrawLinesGpu(context, [{ points, width: 1, color: HV_COLOR }], scrollLeft)) return
101
89
 
102
90
  ctx.save()
103
91
  ctx.translate(-scrollLeft, 0)
@@ -19,6 +19,7 @@ import type { IchimokuRenderState } from '../../indicators/state/ichimokuState'
19
19
  import { createIchimokuStateKey, EMPTY_ICHIMOKU_STATE } from '../../indicators/state/ichimokuState'
20
20
  import { createIchimokuVisibleStateComposer } from '../../indicators/visibleStateComposers'
21
21
  import { getPhysicalKLineConfig } from '../../utils/klineConfig'
22
+ import { tryDrawLinesGpu } from '../linesViaRenderer'
22
23
 
23
24
  const TENKAN_COLOR = '#dc2626'
24
25
  const KIJUN_COLOR = '#2563eb'
@@ -99,16 +100,14 @@ function renderCloudFill(
99
100
  }
100
101
 
101
102
  function renderIchimokuLines(
102
- ctx: CanvasRenderingContext2D,
103
- lineWebGLSurface: RenderContext['lineWebGLSurface'],
104
- scrollLeft: number,
105
- enableWebGL: boolean,
103
+ context: RenderContext,
106
104
  tenkanPts: Point[],
107
105
  kijunPts: Point[],
108
106
  spanAPts: Point[],
109
107
  spanBPts: Point[],
110
108
  chikouPts: Point[],
111
109
  ): void {
110
+ const { ctx, scrollLeft } = context
112
111
  const lines: Array<{ points: Point[]; width: number; color: string }> = []
113
112
  if (tenkanPts.length >= 2) lines.push({ points: tenkanPts, width: 1, color: TENKAN_COLOR })
114
113
  if (kijunPts.length >= 2) lines.push({ points: kijunPts, width: 1, color: KIJUN_COLOR })
@@ -116,13 +115,7 @@ function renderIchimokuLines(
116
115
  if (spanBPts.length >= 2) lines.push({ points: spanBPts, width: 1, color: SPAN_B_COLOR })
117
116
  if (chikouPts.length >= 2) lines.push({ points: chikouPts, width: 1, color: CHIKOU_COLOR })
118
117
 
119
- if (enableWebGL && lineWebGLSurface?.isAvailable()) {
120
- const allOk = lines.length > 0 && lineWebGLSurface.drawLineStrips(lines, scrollLeft)
121
- if (allOk) {
122
- lineWebGLSurface.compositeTo(ctx, { imageSmoothingEnabled: false })
123
- return
124
- }
125
- }
118
+ if (tryDrawLinesGpu(context, lines, scrollLeft)) return
126
119
 
127
120
  ctx.save()
128
121
  ctx.translate(-scrollLeft, 0)
@@ -182,7 +175,7 @@ function createIchimokuRendererPlugin(
182
175
  },
183
176
 
184
177
  draw(context: RenderContext) {
185
- const { ctx, pane, range, scrollLeft, kLineCenters, lineWebGLSurface } = context
178
+ const { ctx, pane, range, scrollLeft, kLineCenters } = context
186
179
  const colors = resolveThemeColors(
187
180
  context.theme,
188
181
  context.isAsiaMarket,
@@ -200,10 +193,7 @@ function createIchimokuRendererPlugin(
200
193
  renderCloudFill(ctx, points.cloudSegs, colors, scrollLeft)
201
194
  }
202
195
  renderIchimokuLines(
203
- ctx,
204
- lineWebGLSurface,
205
- scrollLeft,
206
- context.settings?.enableWebGLRendering !== false,
196
+ context,
207
197
  points.tenkanPts,
208
198
  points.kijunPts,
209
199
  points.spanAPts,
@@ -238,20 +228,27 @@ function fillCloud(
238
228
  bearColor: string,
239
229
  alpha = 0.15,
240
230
  ): void {
231
+ if (segs.length < 2) return
241
232
  ctx.save()
242
233
  ctx.globalAlpha = alpha
243
- for (let i = 0; i < segs.length - 1; i++) {
244
- const a = segs[i]!
245
- const b = segs[i + 1]!
246
- ctx.fillStyle = a.bull ? bullColor : bearColor
234
+
235
+ let start = 0
236
+ const lastSeg = segs.length - 1
237
+ while (start < lastSeg) {
238
+ const isBull = segs[start]!.bull
239
+ ctx.fillStyle = isBull ? bullColor : bearColor
240
+ let end = start
241
+ while (end < lastSeg && segs[end]!.bull === isBull) end++
242
+ end--
247
243
  ctx.beginPath()
248
- ctx.moveTo(a.x, a.ya)
249
- ctx.lineTo(b.x, b.ya)
250
- ctx.lineTo(b.x, b.yb)
251
- ctx.lineTo(a.x, a.yb)
244
+ ctx.moveTo(segs[start]!.x, segs[start]!.ya)
245
+ for (let k = start + 1; k <= end + 1; k++) ctx.lineTo(segs[k]!.x, segs[k]!.ya)
246
+ for (let k = end; k >= start; k--) ctx.lineTo(segs[k]!.x, segs[k]!.yb)
252
247
  ctx.closePath()
253
248
  ctx.fill()
249
+ start = end + 1
254
250
  }
251
+
255
252
  ctx.restore()
256
253
  }
257
254
 
@@ -11,6 +11,7 @@ import type { IndicatorScheduler, KAMASchedulerConfig } from '../../indicators/s
11
11
  import type { KAMARenderState } from '../../indicators/state/kamaState'
12
12
  import { createKAMAStateKey, EMPTY_KAMA_STATE } from '../../indicators/state/kamaState'
13
13
  import { createSparseVisibleStateComposer } from '../../indicators/visibleStateComposers'
14
+ import { tryDrawLinesGpu } from '../linesViaRenderer'
14
15
 
15
16
  import { createSingleLineTitleInfo } from './shared/titleInfo'
16
17
 
@@ -62,7 +63,7 @@ function createKAMARendererPlugin(options: KAMARendererOptions = {}): RendererPl
62
63
  },
63
64
 
64
65
  draw(context: RenderContext) {
65
- const { ctx, pane, range, scrollLeft, kLineCenters, lineWebGLSurface } = context
66
+ const { ctx, pane, range, scrollLeft, kLineCenters } = context
66
67
 
67
68
  const stateKey = resolveKey()
68
69
  if (!stateKey) return
@@ -84,20 +85,7 @@ function createKAMARendererPlugin(options: KAMARendererOptions = {}): RendererPl
84
85
 
85
86
  if (points.length < 2) return
86
87
 
87
- const enableWebGL = context.settings?.enableWebGLRendering !== false
88
- let usedWebGL = false
89
- if (enableWebGL && lineWebGLSurface?.isAvailable()) {
90
- const allOk = lineWebGLSurface.drawLineStrips(
91
- [{ points, width: 1, color: KAMA_COLOR }],
92
- scrollLeft,
93
- )
94
- if (allOk) {
95
- usedWebGL = true
96
- lineWebGLSurface.compositeTo(ctx, { imageSmoothingEnabled: false })
97
- }
98
- }
99
-
100
- if (usedWebGL) return
88
+ if (tryDrawLinesGpu(context, [{ points, width: 1, color: KAMA_COLOR }], scrollLeft)) return
101
89
 
102
90
  ctx.save()
103
91
  ctx.translate(-scrollLeft, 0)
@@ -16,6 +16,7 @@ import type { IndicatorScheduler, KeltnerSchedulerConfig } from '../../indicator
16
16
  import type { KeltnerRenderState } from '../../indicators/state/keltnerState'
17
17
  import { createKeltnerStateKey, EMPTY_KELTNER_STATE } from '../../indicators/state/keltnerState'
18
18
  import { createBandVisibleStateComposer } from '../../indicators/visibleStateComposers'
19
+ import { tryDrawLinesGpu } from '../linesViaRenderer'
19
20
 
20
21
  const KELTNER_UPPER_COLOR = '#7c3aed'
21
22
  const KELTNER_MIDDLE_COLOR = '#f59e0b'
@@ -66,7 +67,7 @@ function createKeltnerRendererPlugin(options: KeltnerRendererOptions = {}): Rend
66
67
  },
67
68
 
68
69
  draw(context: RenderContext) {
69
- const { ctx, pane, range, scrollLeft, kLineCenters, lineWebGLSurface } = context
70
+ const { ctx, pane, range, scrollLeft, kLineCenters } = context
70
71
  const stateKey = resolveKey()
71
72
  if (!stateKey) return
72
73
  const state = pluginHost?.getSharedState<KeltnerRenderState>(stateKey)
@@ -100,17 +101,7 @@ function createKeltnerRendererPlugin(options: KeltnerRendererOptions = {}): Rend
100
101
  if (lowerPts.length >= 2)
101
102
  lines.push({ points: lowerPts, width: 1, color: KELTNER_LOWER_COLOR })
102
103
 
103
- const enableWebGL = context.settings?.enableWebGLRendering !== false
104
- let usedWebGL = false
105
- if (enableWebGL && lineWebGLSurface?.isAvailable()) {
106
- const allOk = lines.length > 0 && lineWebGLSurface.drawLineStrips(lines, scrollLeft)
107
- if (allOk) {
108
- usedWebGL = true
109
- lineWebGLSurface.compositeTo(ctx, { imageSmoothingEnabled: false })
110
- }
111
- }
112
-
113
- if (usedWebGL) return
104
+ if (tryDrawLinesGpu(context, lines, scrollLeft)) return
114
105
 
115
106
  ctx.save()
116
107
  ctx.translate(-scrollLeft, 0)