@lightningjs/renderer 0.6.1 → 0.7.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 (201) hide show
  1. package/dist/src/common/CommonTypes.d.ts +8 -0
  2. package/dist/src/core/CoreNode.d.ts +4 -7
  3. package/dist/src/core/CoreNode.js +73 -40
  4. package/dist/src/core/CoreNode.js.map +1 -1
  5. package/dist/src/core/CoreTextNode.d.ts +12 -2
  6. package/dist/src/core/CoreTextNode.js +46 -1
  7. package/dist/src/core/CoreTextNode.js.map +1 -1
  8. package/dist/src/core/CoreTextureManager.d.ts +3 -1
  9. package/dist/src/core/CoreTextureManager.js +4 -1
  10. package/dist/src/core/CoreTextureManager.js.map +1 -1
  11. package/dist/src/core/Stage.d.ts +6 -0
  12. package/dist/src/core/Stage.js +13 -4
  13. package/dist/src/core/Stage.js.map +1 -1
  14. package/dist/src/core/animations/CoreAnimation.d.ts +1 -0
  15. package/dist/src/core/animations/CoreAnimation.js +7 -0
  16. package/dist/src/core/animations/CoreAnimation.js.map +1 -1
  17. package/dist/src/core/lib/ImageWorker.d.ts +16 -0
  18. package/dist/src/core/lib/ImageWorker.js +111 -0
  19. package/dist/src/core/lib/ImageWorker.js.map +1 -0
  20. package/dist/src/core/lib/WebGlContextWrapper.d.ts +4 -0
  21. package/dist/src/core/lib/WebGlContextWrapper.js +7 -2
  22. package/dist/src/core/lib/WebGlContextWrapper.js.map +1 -1
  23. package/dist/src/core/lib/utils.d.ts +9 -0
  24. package/dist/src/core/lib/utils.js +48 -1
  25. package/dist/src/core/lib/utils.js.map +1 -1
  26. package/dist/src/core/renderers/CoreRenderer.d.ts +2 -2
  27. package/dist/src/core/renderers/webgl/WebGlCoreCtxSubTexture.d.ts +2 -1
  28. package/dist/src/core/renderers/webgl/WebGlCoreCtxSubTexture.js +2 -2
  29. package/dist/src/core/renderers/webgl/WebGlCoreCtxSubTexture.js.map +1 -1
  30. package/dist/src/core/renderers/webgl/WebGlCoreCtxTexture.d.ts +3 -2
  31. package/dist/src/core/renderers/webgl/WebGlCoreCtxTexture.js +23 -21
  32. package/dist/src/core/renderers/webgl/WebGlCoreCtxTexture.js.map +1 -1
  33. package/dist/src/core/renderers/webgl/WebGlCoreRenderOp.d.ts +5 -4
  34. package/dist/src/core/renderers/webgl/WebGlCoreRenderOp.js +10 -14
  35. package/dist/src/core/renderers/webgl/WebGlCoreRenderOp.js.map +1 -1
  36. package/dist/src/core/renderers/webgl/WebGlCoreRenderer.d.ts +4 -1
  37. package/dist/src/core/renderers/webgl/WebGlCoreRenderer.js +30 -24
  38. package/dist/src/core/renderers/webgl/WebGlCoreRenderer.js.map +1 -1
  39. package/dist/src/core/renderers/webgl/WebGlCoreShader.d.ts +2 -1
  40. package/dist/src/core/renderers/webgl/WebGlCoreShader.js +24 -24
  41. package/dist/src/core/renderers/webgl/WebGlCoreShader.js.map +1 -1
  42. package/dist/src/core/renderers/webgl/internal/RendererUtils.d.ts +8 -5
  43. package/dist/src/core/renderers/webgl/internal/RendererUtils.js +11 -13
  44. package/dist/src/core/renderers/webgl/internal/RendererUtils.js.map +1 -1
  45. package/dist/src/core/renderers/webgl/internal/ShaderUtils.d.ts +3 -2
  46. package/dist/src/core/renderers/webgl/internal/ShaderUtils.js +15 -15
  47. package/dist/src/core/renderers/webgl/internal/ShaderUtils.js.map +1 -1
  48. package/dist/src/core/renderers/webgl/shaders/DefaultShader.js +3 -6
  49. package/dist/src/core/renderers/webgl/shaders/DefaultShader.js.map +1 -1
  50. package/dist/src/core/renderers/webgl/shaders/DefaultShaderBatched.js +3 -3
  51. package/dist/src/core/renderers/webgl/shaders/DefaultShaderBatched.js.map +1 -1
  52. package/dist/src/core/renderers/webgl/shaders/DynamicShader.d.ts +1 -0
  53. package/dist/src/core/renderers/webgl/shaders/DynamicShader.js +32 -12
  54. package/dist/src/core/renderers/webgl/shaders/DynamicShader.js.map +1 -1
  55. package/dist/src/core/renderers/webgl/shaders/RoundedRectangle.js +3 -3
  56. package/dist/src/core/renderers/webgl/shaders/RoundedRectangle.js.map +1 -1
  57. package/dist/src/core/renderers/webgl/shaders/SdfShader.js +3 -3
  58. package/dist/src/core/renderers/webgl/shaders/SdfShader.js.map +1 -1
  59. package/dist/src/core/renderers/webgl/shaders/effects/BorderEffect.js +1 -1
  60. package/dist/src/core/renderers/webgl/shaders/effects/GrayscaleEffect.d.ts +14 -1
  61. package/dist/src/core/renderers/webgl/shaders/effects/GrayscaleEffect.js +15 -5
  62. package/dist/src/core/renderers/webgl/shaders/effects/GrayscaleEffect.js.map +1 -1
  63. package/dist/src/core/text-rendering/font-face-types/SdfTrFontFace/SdfTrFontFace.js +3 -3
  64. package/dist/src/core/text-rendering/font-face-types/SdfTrFontFace/SdfTrFontFace.js.map +1 -1
  65. package/dist/src/core/text-rendering/font-face-types/SdfTrFontFace/internal/SdfFontShaper.d.ts +2 -1
  66. package/dist/src/core/text-rendering/font-face-types/SdfTrFontFace/internal/SdfFontShaper.js +4 -2
  67. package/dist/src/core/text-rendering/font-face-types/SdfTrFontFace/internal/SdfFontShaper.js.map +1 -1
  68. package/dist/src/core/text-rendering/renderers/CanvasTextRenderer.d.ts +2 -2
  69. package/dist/src/core/text-rendering/renderers/CanvasTextRenderer.js +25 -0
  70. package/dist/src/core/text-rendering/renderers/CanvasTextRenderer.js.map +1 -1
  71. package/dist/src/core/text-rendering/renderers/LightningTextTextureRenderer.d.ts +1 -1
  72. package/dist/src/core/text-rendering/renderers/LightningTextTextureRenderer.js +6 -6
  73. package/dist/src/core/text-rendering/renderers/LightningTextTextureRenderer.js.map +1 -1
  74. package/dist/src/core/text-rendering/renderers/SdfTextRenderer/SdfTextRenderer.d.ts +8 -11
  75. package/dist/src/core/text-rendering/renderers/SdfTextRenderer/SdfTextRenderer.js +140 -81
  76. package/dist/src/core/text-rendering/renderers/SdfTextRenderer/SdfTextRenderer.js.map +1 -1
  77. package/dist/src/core/text-rendering/renderers/SdfTextRenderer/internal/findNearestMultiple.d.ts +8 -0
  78. package/dist/src/core/text-rendering/renderers/SdfTextRenderer/internal/findNearestMultiple.js +29 -0
  79. package/dist/src/core/text-rendering/renderers/SdfTextRenderer/internal/findNearestMultiple.js.map +1 -0
  80. package/dist/src/core/text-rendering/renderers/SdfTextRenderer/internal/getStartConditions.d.ts +4 -3
  81. package/dist/src/core/text-rendering/renderers/SdfTextRenderer/internal/getStartConditions.js +15 -11
  82. package/dist/src/core/text-rendering/renderers/SdfTextRenderer/internal/getStartConditions.js.map +1 -1
  83. package/dist/src/core/text-rendering/renderers/SdfTextRenderer/internal/layoutText.d.ts +3 -2
  84. package/dist/src/core/text-rendering/renderers/SdfTextRenderer/internal/layoutText.js +30 -26
  85. package/dist/src/core/text-rendering/renderers/SdfTextRenderer/internal/layoutText.js.map +1 -1
  86. package/dist/src/core/text-rendering/renderers/SdfTextRenderer/internal/layoutText2/SdfBufferHelper.d.ts +19 -0
  87. package/dist/src/core/text-rendering/renderers/SdfTextRenderer/internal/layoutText2/SdfBufferHelper.js +84 -0
  88. package/dist/src/core/text-rendering/renderers/SdfTextRenderer/internal/layoutText2/SdfBufferHelper.js.map +1 -0
  89. package/dist/src/core/text-rendering/renderers/SdfTextRenderer/internal/layoutText2/layoutLine.d.ts +8 -0
  90. package/dist/src/core/text-rendering/renderers/SdfTextRenderer/internal/layoutText2/layoutLine.js +40 -0
  91. package/dist/src/core/text-rendering/renderers/SdfTextRenderer/internal/layoutText2/layoutLine.js.map +1 -0
  92. package/dist/src/core/text-rendering/renderers/SdfTextRenderer/internal/layoutText2/layoutText2.d.ts +2 -0
  93. package/dist/src/core/text-rendering/renderers/SdfTextRenderer/internal/layoutText2/layoutText2.js +41 -0
  94. package/dist/src/core/text-rendering/renderers/SdfTextRenderer/internal/layoutText2/layoutText2.js.map +1 -0
  95. package/dist/src/core/text-rendering/renderers/SdfTextRenderer/internal/layoutText2/utils.d.ts +1 -0
  96. package/dist/src/core/text-rendering/renderers/SdfTextRenderer/internal/layoutText2/utils.js +4 -0
  97. package/dist/src/core/text-rendering/renderers/SdfTextRenderer/internal/layoutText2/utils.js.map +1 -0
  98. package/dist/src/core/text-rendering/renderers/SdfTextRenderer/internal/layoutText2.d.ts +1 -0
  99. package/dist/src/core/text-rendering/renderers/SdfTextRenderer/internal/layoutText2.js +2 -0
  100. package/dist/src/core/text-rendering/renderers/SdfTextRenderer/internal/layoutText2.js.map +1 -0
  101. package/dist/src/core/text-rendering/renderers/SdfTextRenderer/internal/roundUpToMultiple.d.ts +9 -0
  102. package/dist/src/core/text-rendering/renderers/SdfTextRenderer/internal/roundUpToMultiple.js +32 -0
  103. package/dist/src/core/text-rendering/renderers/SdfTextRenderer/internal/roundUpToMultiple.js.map +1 -0
  104. package/dist/src/core/text-rendering/renderers/SdfTextRenderer/internal/setRenderWindow.d.ts +26 -0
  105. package/dist/src/core/text-rendering/renderers/SdfTextRenderer/internal/setRenderWindow.js +70 -0
  106. package/dist/src/core/text-rendering/renderers/SdfTextRenderer/internal/setRenderWindow.js.map +1 -0
  107. package/dist/src/core/text-rendering/renderers/SdfTextRenderer/internal/util.d.ts +16 -0
  108. package/dist/src/core/text-rendering/renderers/SdfTextRenderer/internal/util.js +39 -0
  109. package/dist/src/core/text-rendering/renderers/SdfTextRenderer/internal/util.js.map +1 -0
  110. package/dist/src/core/text-rendering/renderers/TextRenderer.d.ts +52 -2
  111. package/dist/src/core/text-rendering/renderers/TextRenderer.js +19 -0
  112. package/dist/src/core/text-rendering/renderers/TextRenderer.js.map +1 -1
  113. package/dist/src/core/textures/ImageTexture.js +14 -9
  114. package/dist/src/core/textures/ImageTexture.js.map +1 -1
  115. package/dist/src/core/utils.d.ts +1 -6
  116. package/dist/src/core/utils.js +3 -2
  117. package/dist/src/core/utils.js.map +1 -1
  118. package/dist/src/main-api/ICoreDriver.d.ts +2 -1
  119. package/dist/src/main-api/RendererMain.d.ts +25 -0
  120. package/dist/src/main-api/RendererMain.js +14 -5
  121. package/dist/src/main-api/RendererMain.js.map +1 -1
  122. package/dist/src/render-drivers/main/MainCoreDriver.d.ts +2 -1
  123. package/dist/src/render-drivers/main/MainCoreDriver.js +6 -4
  124. package/dist/src/render-drivers/main/MainCoreDriver.js.map +1 -1
  125. package/dist/src/render-drivers/main/MainOnlyTextNode.d.ts +10 -0
  126. package/dist/src/render-drivers/main/MainOnlyTextNode.js +45 -0
  127. package/dist/src/render-drivers/main/MainOnlyTextNode.js.map +1 -1
  128. package/dist/src/render-drivers/threadx/TextNodeStruct.d.ts +10 -0
  129. package/dist/src/render-drivers/threadx/TextNodeStruct.js +45 -0
  130. package/dist/src/render-drivers/threadx/TextNodeStruct.js.map +1 -1
  131. package/dist/src/render-drivers/threadx/ThreadXCoreDriver.d.ts +2 -1
  132. package/dist/src/render-drivers/threadx/ThreadXCoreDriver.js +8 -1
  133. package/dist/src/render-drivers/threadx/ThreadXCoreDriver.js.map +1 -1
  134. package/dist/src/render-drivers/threadx/ThreadXMainTextNode.d.ts +5 -0
  135. package/dist/src/render-drivers/threadx/ThreadXMainTextNode.js +5 -0
  136. package/dist/src/render-drivers/threadx/ThreadXMainTextNode.js.map +1 -1
  137. package/dist/src/render-drivers/threadx/ThreadXRendererMessage.d.ts +4 -1
  138. package/dist/src/render-drivers/threadx/ThreadXRendererMessage.js.map +1 -1
  139. package/dist/src/render-drivers/threadx/worker/ThreadXRendererTextNode.d.ts +5 -0
  140. package/dist/src/render-drivers/threadx/worker/ThreadXRendererTextNode.js +10 -0
  141. package/dist/src/render-drivers/threadx/worker/ThreadXRendererTextNode.js.map +1 -1
  142. package/dist/src/render-drivers/threadx/worker/renderer.js +5 -3
  143. package/dist/src/render-drivers/threadx/worker/renderer.js.map +1 -1
  144. package/dist/src/utils.d.ts +2 -1
  145. package/dist/src/utils.js +22 -3
  146. package/dist/src/utils.js.map +1 -1
  147. package/dist/tsconfig.dist.tsbuildinfo +1 -1
  148. package/package.json +3 -2
  149. package/src/common/CommonTypes.ts +9 -0
  150. package/src/core/CoreNode.ts +96 -62
  151. package/src/core/CoreTextNode.ts +58 -2
  152. package/src/core/CoreTextureManager.ts +4 -2
  153. package/src/core/Stage.ts +33 -4
  154. package/src/core/animations/CoreAnimation.ts +8 -0
  155. package/src/core/lib/ContextSpy.ts +41 -0
  156. package/src/core/lib/ImageWorker.ts +124 -0
  157. package/src/core/lib/WebGlContextWrapper.ts +965 -0
  158. package/src/core/lib/utils.ts +68 -1
  159. package/src/core/renderers/CoreRenderer.ts +2 -2
  160. package/src/core/renderers/webgl/WebGlCoreCtxSubTexture.ts +3 -2
  161. package/src/core/renderers/webgl/WebGlCoreCtxTexture.ts +29 -28
  162. package/src/core/renderers/webgl/WebGlCoreRenderOp.ts +13 -17
  163. package/src/core/renderers/webgl/WebGlCoreRenderer.ts +33 -25
  164. package/src/core/renderers/webgl/WebGlCoreShader.ts +34 -25
  165. package/src/core/renderers/webgl/internal/RendererUtils.ts +13 -16
  166. package/src/core/renderers/webgl/internal/ShaderUtils.ts +16 -15
  167. package/src/core/renderers/webgl/shaders/DefaultShader.ts +3 -7
  168. package/src/core/renderers/webgl/shaders/DefaultShaderBatched.ts +3 -3
  169. package/src/core/renderers/webgl/shaders/DynamicShader.ts +42 -14
  170. package/src/core/renderers/webgl/shaders/RoundedRectangle.ts +3 -3
  171. package/src/core/renderers/webgl/shaders/SdfShader.ts +3 -3
  172. package/src/core/renderers/webgl/shaders/effects/BorderEffect.ts +1 -1
  173. package/src/core/renderers/webgl/shaders/effects/GrayscaleEffect.ts +35 -5
  174. package/src/core/text-rendering/font-face-types/SdfTrFontFace/SdfTrFontFace.ts +3 -3
  175. package/src/core/text-rendering/font-face-types/SdfTrFontFace/internal/SdfFontShaper.test.ts +9 -3
  176. package/src/core/text-rendering/font-face-types/SdfTrFontFace/internal/SdfFontShaper.ts +4 -2
  177. package/src/core/text-rendering/renderers/CanvasTextRenderer.ts +27 -1
  178. package/src/core/text-rendering/renderers/LightningTextTextureRenderer.ts +7 -7
  179. package/src/core/text-rendering/renderers/SdfTextRenderer/SdfTextRenderer.ts +193 -103
  180. package/src/core/text-rendering/renderers/SdfTextRenderer/internal/getStartConditions.ts +26 -18
  181. package/src/core/text-rendering/renderers/SdfTextRenderer/internal/layoutText.ts +40 -28
  182. package/src/core/text-rendering/renderers/SdfTextRenderer/internal/measureText.test.ts +6 -1
  183. package/src/core/text-rendering/renderers/SdfTextRenderer/internal/setRenderWindow.test.ts +205 -0
  184. package/src/core/text-rendering/renderers/SdfTextRenderer/internal/{makeRenderWindow.ts → setRenderWindow.ts} +50 -21
  185. package/src/core/text-rendering/renderers/SdfTextRenderer/internal/util.ts +40 -0
  186. package/src/core/text-rendering/renderers/TextRenderer.ts +75 -2
  187. package/src/core/textures/ImageTexture.ts +17 -9
  188. package/src/core/utils.ts +87 -85
  189. package/src/env.d.ts +7 -0
  190. package/src/main-api/ICoreDriver.ts +2 -1
  191. package/src/main-api/RendererMain.ts +43 -5
  192. package/src/render-drivers/main/MainCoreDriver.ts +8 -5
  193. package/src/render-drivers/main/MainOnlyTextNode.ts +55 -1
  194. package/src/render-drivers/threadx/TextNodeStruct.ts +45 -0
  195. package/src/render-drivers/threadx/ThreadXCoreDriver.ts +10 -2
  196. package/src/render-drivers/threadx/ThreadXMainTextNode.ts +10 -0
  197. package/src/render-drivers/threadx/ThreadXRendererMessage.ts +5 -1
  198. package/src/render-drivers/threadx/worker/ThreadXRendererTextNode.ts +15 -0
  199. package/src/render-drivers/threadx/worker/renderer.ts +6 -4
  200. package/src/utils.ts +25 -4
  201. package/src/core/text-rendering/renderers/SdfTextRenderer/internal/makeRenderWindow.test.ts +0 -136
@@ -18,6 +18,7 @@
18
18
  */
19
19
 
20
20
  import { assertTruthy } from '../../../../../utils.js';
21
+ import type { Bound } from '../../../../lib/utils.js';
21
22
  import type {
22
23
  FontShaperProps,
23
24
  MappedGlyphInfo,
@@ -38,6 +39,7 @@ export function layoutText(
38
39
  width: TrProps['width'],
39
40
  height: TrProps['height'],
40
41
  fontSize: TrProps['fontSize'],
42
+ lineHeight: TrProps['lineHeight'],
41
43
  letterSpacing: TrProps['letterSpacing'],
42
44
  /**
43
45
  * Mutated
@@ -48,10 +50,12 @@ export function layoutText(
48
50
  * Mutated
49
51
  */
50
52
  lineCache: SdfTextRendererState['lineCache'],
51
- renderWindow: SdfTextRendererState['renderWindow'],
53
+ rwSdf: Bound,
52
54
  trFontFace: SdfTextRendererState['trFontFace'],
53
55
  forceFullLayoutCalc: TextRendererState['forceFullLayoutCalc'],
54
56
  scrollable: TrProps['scrollable'],
57
+ overflowSuffix: TrProps['overflowSuffix'],
58
+ maxLines: TrProps['maxLines'],
55
59
  ): {
56
60
  bufferNumFloats: number;
57
61
  bufferNumQuads: number;
@@ -75,13 +79,13 @@ export function layoutText(
75
79
  // We convert these to the vertex space by dividing them the `fontSizeRatio` factor.
76
80
 
77
81
  /**
78
- * `lineHeight` in vertex coordinates
82
+ * See above
79
83
  */
80
- const vertexLineHeight = trFontFace.data.info.size;
84
+ const fontSizeRatio = fontSize / trFontFace.data.info.size;
81
85
  /**
82
- * See above
86
+ * `lineHeight` in vertex coordinates
83
87
  */
84
- const fontSizeRatio = fontSize / vertexLineHeight;
88
+ const vertexLineHeight = lineHeight / fontSizeRatio;
85
89
  /**
86
90
  * `w` in vertex coordinates
87
91
  */
@@ -142,24 +146,32 @@ export function layoutText(
142
146
  bufferEnd: number;
143
147
  }[] = [];
144
148
 
145
- const truncateSeq = '...';
146
149
  const vertexTruncateHeight = height / fontSizeRatio;
147
- const truncateSeqVertexWidth = measureText(truncateSeq, shaperProps, shaper);
150
+ const overflowSuffVertexWidth = measureText(
151
+ overflowSuffix,
152
+ shaperProps,
153
+ shaper,
154
+ );
148
155
 
149
156
  // Line-by-line layout
150
157
  let moreLines = true;
151
158
  while (moreLines) {
152
159
  const nextLineWillFit =
153
- contain !== 'both' ||
154
- scrollable ||
155
- curY + vertexLineHeight + vertexLineHeight <= vertexTruncateHeight;
160
+ (maxLines === 0 || curLineIndex + 1 < maxLines) &&
161
+ (contain !== 'both' ||
162
+ scrollable ||
163
+ curY + vertexLineHeight + vertexLineHeight <= vertexTruncateHeight);
156
164
  const lineVertexW = nextLineWillFit
157
165
  ? vertexW
158
- : vertexW - truncateSeqVertexWidth;
166
+ : vertexW - overflowSuffVertexWidth;
159
167
  /**
160
168
  * Vertex X position to the beginning of the last word boundary. This becomes -1 when we start traversing a word.
161
169
  */
162
170
  let xStartLastWordBoundary = 0;
171
+
172
+ const lineIsBelowWindowTop = curY + vertexLineHeight >= rwSdf.y1;
173
+ const lineIsAboveWindowBottom = curY <= rwSdf.y2;
174
+ const lineIsWithinWindow = lineIsBelowWindowTop && lineIsAboveWindowBottom;
163
175
  // Layout glyphs in this line
164
176
  // Any break statements in this while loop will trigger a line break
165
177
  while ((glyphResult = glyphs.next()) && !glyphResult.done) {
@@ -220,7 +232,7 @@ export function layoutText(
220
232
  } else {
221
233
  glyphs = shaper.shapeText(
222
234
  shaperProps,
223
- new PeekableIterator(getUnicodeCodepoints(truncateSeq, 0), 0),
235
+ new PeekableIterator(getUnicodeCodepoints(overflowSuffix, 0), 0),
224
236
  );
225
237
  curX = lastWord.xStart;
226
238
  bufferOffset = lastWord.bufferOffset;
@@ -230,15 +242,8 @@ export function layoutText(
230
242
  const quadX = curX + glyph.xOffset;
231
243
  const quadY = curY + glyph.yOffset;
232
244
 
233
- const lineIsBelowWindowTop = renderWindow
234
- ? curY + vertexLineHeight >= renderWindow.y1 / fontSizeRatio
235
- : true;
236
- const lineIsAboveWindowBottom = renderWindow
237
- ? curY <= renderWindow.y2 / fontSizeRatio
238
- : true;
239
-
240
245
  // Only add to buffer for rendering if the line is within the render window
241
- if (lineIsBelowWindowTop && lineIsAboveWindowBottom) {
246
+ if (lineIsWithinWindow) {
242
247
  if (curLineBufferStart === -1) {
243
248
  curLineBufferStart = bufferOffset;
244
249
  }
@@ -288,7 +293,19 @@ export function layoutText(
288
293
 
289
294
  // Handle newlines
290
295
  if (glyph.codepoint === 10) {
291
- break;
296
+ if (nextLineWillFit) {
297
+ // The whole line fit, so we can break to the next line
298
+ break;
299
+ } else {
300
+ // The whole line won't fit, so we need to add the overflow suffix
301
+ glyphs = shaper.shapeText(
302
+ shaperProps,
303
+ new PeekableIterator(getUnicodeCodepoints(overflowSuffix, 0), 0),
304
+ );
305
+ // HACK: For the rest of the line when inserting the overflow suffix,
306
+ // set contain = 'none' to prevent an infinite loop.
307
+ contain = 'none';
308
+ }
292
309
  }
293
310
  }
294
311
  }
@@ -308,12 +325,7 @@ export function layoutText(
308
325
  xStartLastWordBoundary = 0;
309
326
 
310
327
  // Figure out if there are any more lines to render...
311
- if (
312
- !forceFullLayoutCalc &&
313
- contain === 'both' &&
314
- renderWindow &&
315
- curY > renderWindow.y2 / fontSizeRatio
316
- ) {
328
+ if (!forceFullLayoutCalc && contain === 'both' && curY > rwSdf.y2) {
317
329
  // Stop layout calculation early (for performance purposes) if:
318
330
  // - We're not forcing a full layout calculation (for width/height calculation)
319
331
  // - ...and we're containing the text vertically+horizontally (contain === 'both')
@@ -323,7 +335,7 @@ export function layoutText(
323
335
  } else if (glyphResult && glyphResult.done) {
324
336
  // If we've reached the end of the text, we know we're done
325
337
  moreLines = false;
326
- } else if (contain === 'both' && !scrollable && !nextLineWillFit) {
338
+ } else if (!nextLineWillFit) {
327
339
  // If we're contained vertically+horizontally (contain === 'both')
328
340
  // but not scrollable and the next line won't fit, we're done.
329
341
  moreLines = false;
@@ -25,10 +25,15 @@ import {
25
25
  type SdfFontData,
26
26
  } from '../../../font-face-types/SdfTrFontFace/internal/SdfFontShaper.js';
27
27
 
28
+ const glyphMap = new Map<number, SdfFontData['chars'][0]>();
29
+ sdfData.chars.forEach((glyph) => {
30
+ glyphMap.set(glyph.id, glyph);
31
+ });
32
+
28
33
  describe('measureText', () => {
29
34
  it('should measure text width', () => {
30
35
  const PERIOD_WIDTH = 10.332;
31
- const shaper = new SdfFontShaper(sdfData as unknown as SdfFontData);
36
+ const shaper = new SdfFontShaper(sdfData as unknown as SdfFontData, glyphMap);
32
37
  expect(measureText('', { letterSpacing: 0 }, shaper)).toBe(0);
33
38
  expect(measureText('.', { letterSpacing: 0 }, shaper)).toBe(PERIOD_WIDTH);
34
39
  expect(measureText('..', { letterSpacing: 0 }, shaper)).toBeCloseTo(
@@ -0,0 +1,205 @@
1
+ /*
2
+ * If not stated otherwise in this file or this component's LICENSE file the
3
+ * following copyright and licenses apply:
4
+ *
5
+ * Copyright 2023 Comcast Cable Communications Management, LLC.
6
+ *
7
+ * Licensed under the Apache License, Version 2.0 (the License);
8
+ * you may not use this file except in compliance with the License.
9
+ * You may obtain a copy of the License at
10
+ *
11
+ * http://www.apache.org/licenses/LICENSE-2.0
12
+ *
13
+ * Unless required by applicable law or agreed to in writing, software
14
+ * distributed under the License is distributed on an "AS IS" BASIS,
15
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
16
+ * See the License for the specific language governing permissions and
17
+ * limitations under the License.
18
+ */
19
+
20
+ import { expect, describe, it } from 'vitest';
21
+ import { setRenderWindow, type SdfRenderWindow } from './setRenderWindow.js';
22
+
23
+ function makeRenderWindow(): SdfRenderWindow {
24
+ return {
25
+ screen: { x1: 0, y1: 0, x2: 0, y2: 0 },
26
+ sdf: { x1: 0, y1: 0, x2: 0, y2: 0 },
27
+ firstLineIdx: 0,
28
+ numLines: 0,
29
+ valid: false,
30
+ };
31
+ }
32
+
33
+ describe('setRenderWindow', () => {
34
+ it('should return a empty window when visibleWindow is empty', () => {
35
+ const rw = makeRenderWindow();
36
+ setRenderWindow(rw, 0, 0, 0, 10, 0, { x1: 0, y1: 0, x2: 0, y2: 0 }, 1);
37
+ expect(rw).toEqual({
38
+ screen: { x1: 0, y1: 0, x2: 0, y2: 0 },
39
+ sdf: { x1: 0, y1: 0, x2: 0, y2: 0 },
40
+ firstLineIdx: 0,
41
+ numLines: 0,
42
+ valid: true,
43
+ });
44
+
45
+ setRenderWindow(
46
+ rw,
47
+ 0,
48
+ 0,
49
+ 0,
50
+ 20,
51
+ 0,
52
+ { x1: 100, y1: 100, x2: 100, y2: 100 },
53
+ 2,
54
+ );
55
+ expect(rw).toEqual({
56
+ screen: { x1: 0, y1: 0, x2: 0, y2: 0 },
57
+ sdf: { x1: 0, y1: 0, x2: 0, y2: 0 },
58
+ firstLineIdx: 0,
59
+ numLines: 0,
60
+ valid: true,
61
+ });
62
+
63
+ setRenderWindow(
64
+ rw,
65
+ 100,
66
+ 200,
67
+ 300,
68
+ 10,
69
+ 30,
70
+ { x1: 0, y1: 0, x2: 0, y2: 0 },
71
+ 1,
72
+ );
73
+ expect(rw).toEqual({
74
+ screen: { x1: 0, y1: 0, x2: 0, y2: 0 },
75
+ sdf: { x1: 0, y1: 0, x2: 0, y2: 0 },
76
+ firstLineIdx: 0,
77
+ numLines: 0,
78
+ valid: true,
79
+ });
80
+ setRenderWindow(
81
+ rw,
82
+ 400,
83
+ 500,
84
+ 100,
85
+ 20,
86
+ 40,
87
+ {
88
+ x1: 100,
89
+ y1: 100,
90
+ x2: 100,
91
+ y2: 100,
92
+ },
93
+ 1,
94
+ ),
95
+ expect(rw).toEqual({
96
+ screen: { x1: 0, y1: 0, x2: 0, y2: 0 },
97
+ sdf: { x1: 0, y1: 0, x2: 0, y2: 0 },
98
+ firstLineIdx: 0,
99
+ numLines: 0,
100
+ valid: true,
101
+ });
102
+ });
103
+
104
+ it('should return a window with no margin around the visible area if lineHeight and/or bufferMargin set are zero', () => {
105
+ const rw = makeRenderWindow();
106
+
107
+ setRenderWindow(rw, 0, 0, 0, 10, 0, { x1: 0, y1: 0, x2: 100, y2: 100 }, 1),
108
+ expect(rw).toEqual({
109
+ screen: { x1: 0, y1: 0, x2: 100, y2: 100 },
110
+ sdf: { x1: 0, y1: 0, x2: 100, y2: 100 },
111
+ firstLineIdx: 0,
112
+ numLines: 10,
113
+ valid: true,
114
+ });
115
+
116
+ setRenderWindow(rw, 0, 0, 0, 10, 0, { x1: 0, y1: 0, x2: 200, y2: 205 }, 2);
117
+ expect(rw).toEqual({
118
+ screen: { x1: 0, y1: 0, x2: 200, y2: 210 },
119
+ sdf: { x1: 0, y1: 0, x2: 100, y2: 105 },
120
+ firstLineIdx: 0,
121
+ numLines: 21,
122
+ valid: true,
123
+ });
124
+ });
125
+
126
+ it('should return a window with a margin around the visible area (if boundsMargin set)', () => {
127
+ const rw = makeRenderWindow();
128
+
129
+ setRenderWindow(
130
+ rw,
131
+ 0,
132
+ 0,
133
+ 0,
134
+ 10,
135
+ 100,
136
+ { x1: 0, y1: 0, x2: 100, y2: 100 },
137
+ 1,
138
+ ),
139
+ expect(rw).toEqual({
140
+ screen: { x1: 0, y1: -100, x2: 100, y2: 200 },
141
+ sdf: { x1: 0, y1: -100, x2: 100, y2: 200 },
142
+ firstLineIdx: -10,
143
+ numLines: 30,
144
+ valid: true,
145
+ });
146
+
147
+ setRenderWindow(
148
+ rw,
149
+ 0,
150
+ 0,
151
+ 0,
152
+ 10,
153
+ 200,
154
+ { x1: 0, y1: 0, x2: 200, y2: 200 },
155
+ 1,
156
+ );
157
+ expect(rw).toEqual({
158
+ screen: { x1: 0, y1: -200, x2: 200, y2: 400 },
159
+ sdf: { x1: 0, y1: -200, x2: 200, y2: 400 },
160
+ firstLineIdx: -20,
161
+ numLines: 60,
162
+ valid: true,
163
+ });
164
+ });
165
+
166
+ it('should return a window scrolled to scrollY when set', () => {
167
+ const rw = makeRenderWindow();
168
+
169
+ setRenderWindow(
170
+ rw,
171
+ 0,
172
+ 0,
173
+ 100,
174
+ 10,
175
+ 100,
176
+ { x1: 0, y1: 0, x2: 100, y2: 100 },
177
+ 1,
178
+ ),
179
+ expect(rw).toEqual({
180
+ screen: { x1: 0, y1: 0, x2: 100, y2: 300 },
181
+ sdf: { x1: 0, y1: 0, x2: 100, y2: 300 },
182
+ firstLineIdx: 0,
183
+ numLines: 30,
184
+ valid: true,
185
+ });
186
+
187
+ setRenderWindow(
188
+ rw,
189
+ 0,
190
+ 0,
191
+ 105,
192
+ 10,
193
+ 100,
194
+ { x1: 0, y1: 0, x2: 100, y2: 100 },
195
+ 1,
196
+ ),
197
+ expect(rw).toEqual({
198
+ screen: { x1: 0, y1: 0, x2: 100, y2: 310 },
199
+ sdf: { x1: 0, y1: 0, x2: 100, y2: 310 },
200
+ firstLineIdx: 0,
201
+ numLines: 31,
202
+ valid: true,
203
+ });
204
+ });
205
+ });
@@ -19,6 +19,15 @@
19
19
 
20
20
  import { isBoundPositive, type Bound } from '../../../../lib/utils.js';
21
21
  import type { TrProps } from '../../TextRenderer.js';
22
+ import { roundDownToMultiple, roundUpToMultiple } from './util.js';
23
+
24
+ export interface SdfRenderWindow {
25
+ screen: Bound;
26
+ sdf: Bound;
27
+ firstLineIdx: number;
28
+ numLines: number;
29
+ valid: boolean;
30
+ }
22
31
 
23
32
  /**
24
33
  * Create a render window from the given parameters.
@@ -32,33 +41,53 @@ import type { TrProps } from '../../TextRenderer.js';
32
41
  * @param x The x coordinate of the text element's top left corner relative to the screen.
33
42
  * @param y The y coordinate of the text element's top left corner relative to the screen.
34
43
  * @param scrollY The amount of pixels to scroll the text vertically.
35
- * @param lineHeight The height of a single line of text.
36
- * @param numExtraLines The number of extra lines to render above and below the visible window.
44
+ * @param lineHeight The number of extra lines to render above and below the visible window.
37
45
  * @param visibleWindow The visible window of the text element relative to the screen
38
46
  * @returns
39
47
  */
40
- export function makeRenderWindow(
48
+ export function setRenderWindow(
49
+ outRenderWindow: SdfRenderWindow,
41
50
  x: TrProps['x'],
42
51
  y: TrProps['y'],
43
52
  scrollY: TrProps['scrollY'],
44
53
  lineHeight: number,
45
- numExtraLines: number,
54
+ bufferMargin: number,
46
55
  visibleWindow: Bound,
47
- ): Bound {
48
- const bufferMargin = lineHeight * numExtraLines;
49
- const x1 = visibleWindow.x1 - x;
50
- const y1 = visibleWindow.y1 - y;
51
- return isBoundPositive(visibleWindow)
52
- ? {
53
- x1: x1,
54
- y1: y1 + scrollY - bufferMargin,
55
- x2: x1 + (visibleWindow.x2 - visibleWindow.x1),
56
- y2: y1 + scrollY + (visibleWindow.y2 - visibleWindow.y1) + bufferMargin,
57
- }
58
- : {
59
- x1: 0,
60
- y1: 0,
61
- x2: 0,
62
- y2: 0,
63
- };
56
+ fontSizeRatio: number,
57
+ ): void {
58
+ const { screen, sdf } = outRenderWindow;
59
+ if (!isBoundPositive(visibleWindow)) {
60
+ screen.x1 = 0;
61
+ screen.y1 = 0;
62
+ screen.x2 = 0;
63
+ screen.y2 = 0;
64
+ sdf.x1 = 0;
65
+ sdf.y1 = 0;
66
+ sdf.x2 = 0;
67
+ sdf.y2 = 0;
68
+ outRenderWindow.numLines = 0;
69
+ outRenderWindow.firstLineIdx = 0;
70
+ } else {
71
+ const x1 = visibleWindow.x1 - x;
72
+ const x2 = x1 + (visibleWindow.x2 - visibleWindow.x1);
73
+ const y1Base = visibleWindow.y1 - y + scrollY;
74
+ const y1 = roundDownToMultiple(y1Base - bufferMargin, lineHeight || 1);
75
+ const y2 = roundUpToMultiple(
76
+ y1Base + (visibleWindow.y2 - visibleWindow.y1) + bufferMargin,
77
+ lineHeight || 1,
78
+ );
79
+
80
+ screen.x1 = x1;
81
+ screen.y1 = y1;
82
+ screen.x2 = x2;
83
+ screen.y2 = y2;
84
+ sdf.x1 = x1 / fontSizeRatio;
85
+ sdf.y1 = y1 / fontSizeRatio;
86
+ sdf.x2 = x2 / fontSizeRatio;
87
+ sdf.y2 = y2 / fontSizeRatio;
88
+
89
+ outRenderWindow.numLines = Math.ceil((y2 - y1) / lineHeight);
90
+ outRenderWindow.firstLineIdx = lineHeight ? Math.floor(y1 / lineHeight) : 0;
91
+ }
92
+ outRenderWindow.valid = true;
64
93
  }
@@ -0,0 +1,40 @@
1
+ /*
2
+ * If not stated otherwise in this file or this component's LICENSE file the
3
+ * following copyright and licenses apply:
4
+ *
5
+ * Copyright 2023 Comcast Cable Communications Management, LLC.
6
+ *
7
+ * Licensed under the Apache License, Version 2.0 (the License);
8
+ * you may not use this file except in compliance with the License.
9
+ * You may obtain a copy of the License at
10
+ *
11
+ * http://www.apache.org/licenses/LICENSE-2.0
12
+ *
13
+ * Unless required by applicable law or agreed to in writing, software
14
+ * distributed under the License is distributed on an "AS IS" BASIS,
15
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
16
+ * See the License for the specific language governing permissions and
17
+ * limitations under the License.
18
+ */
19
+
20
+ /**
21
+ * Round up to the nearest multiple of the given number.
22
+ *
23
+ * @param value
24
+ * @param multiple
25
+ * @returns
26
+ */
27
+ export function roundUpToMultiple(value: number, multiple: number) {
28
+ return Math.ceil(value / multiple) * multiple;
29
+ }
30
+
31
+ /**
32
+ * Round down to the nearest multiple of the given number.
33
+ *
34
+ * @param value
35
+ * @param multiple
36
+ * @returns
37
+ */
38
+ export function roundDownToMultiple(value: number, multiple: number) {
39
+ return Math.floor(value / multiple) * multiple;
40
+ }
@@ -20,11 +20,15 @@
20
20
  import type { EventEmitter } from '../../../common/EventEmitter.js';
21
21
  import type { Stage } from '../../Stage.js';
22
22
  import type { Matrix3d } from '../../lib/Matrix3d.js';
23
- import type { Rect } from '../../lib/utils.js';
23
+ import type { Rect, RectWithValid } from '../../lib/utils.js';
24
24
  import type {
25
25
  TrFontFace,
26
26
  TrFontFaceDescriptors,
27
27
  } from '../font-face-types/TrFontFace.js';
28
+ import type {
29
+ TextBaseline,
30
+ TextVerticalAlign,
31
+ } from './LightningTextTextureRenderer.js';
28
32
 
29
33
  /**
30
34
  * Augmentable map of text renderer type IDs to text renderer types.
@@ -244,6 +248,56 @@ export interface TrProps extends TrFontProps {
244
248
  * @default 0
245
249
  */
246
250
  letterSpacing: number;
251
+ /**
252
+ * Line height for text (in pixels)
253
+ *
254
+ * @remarks
255
+ * This property sets the height of each line.
256
+ *
257
+ * @default 0
258
+ */
259
+ lineHeight: number;
260
+ /**
261
+ * Max lines for text
262
+ *
263
+ * @remarks
264
+ * This property sets max number of lines of a text paragraph.
265
+ * Not yet implemented in the SDF renderer.
266
+ *
267
+ * @default 0
268
+ */
269
+ maxLines: number;
270
+ /**
271
+ * Baseline for text
272
+ *
273
+ * @remarks
274
+ * This property sets the text baseline used when drawing text.
275
+ * Not yet implemented in the SDF renderer.
276
+ *
277
+ * @default alphabetic
278
+ */
279
+ textBaseline: TextBaseline;
280
+ /**
281
+ * Vertical Align for text when lineHeight > fontSize
282
+ *
283
+ * @remarks
284
+ * This property sets the vertical align of the text.
285
+ * Not yet implemented in the SDF renderer.
286
+ *
287
+ * @default middle
288
+ */
289
+ verticalAlign: TextVerticalAlign;
290
+ /**
291
+ * Overflow Suffix for text
292
+ *
293
+ * @remarks
294
+ * The suffix to be added when text is cropped due to overflow.
295
+ * Not yet implemented in the SDF renderer.
296
+ *
297
+ * @default "..."
298
+ */
299
+ overflowSuffix: string;
300
+
247
301
  zIndex: number;
248
302
  debug: Partial<TextRendererDebugProps>;
249
303
  }
@@ -307,6 +361,21 @@ const trPropSetterDefaults: TrPropSetters = {
307
361
  letterSpacing: (state, value) => {
308
362
  state.props.letterSpacing = value;
309
363
  },
364
+ lineHeight: (state, value) => {
365
+ state.props.lineHeight = value;
366
+ },
367
+ maxLines: (state, value) => {
368
+ state.props.maxLines = value;
369
+ },
370
+ textBaseline: (state, value) => {
371
+ state.props.textBaseline = value;
372
+ },
373
+ verticalAlign: (state, value) => {
374
+ state.props.verticalAlign = value;
375
+ },
376
+ overflowSuffix: (state, value) => {
377
+ state.props.overflowSuffix = value;
378
+ },
310
379
  debug: (state, value) => {
311
380
  state.props.debug = value;
312
381
  },
@@ -348,6 +417,10 @@ export abstract class TextRenderer<
348
417
  (state: StateT, value: TrProps[keyof TrProps]) => {
349
418
  if (state.props[key as keyof TrProps] !== value) {
350
419
  setter(state, value as never);
420
+ // Assume any prop change will require a render
421
+ // This is required because otherwise a paused RAF will result
422
+ // in renders when text props are changed.
423
+ this.stage.requestRender();
351
424
  }
352
425
  },
353
426
  ];
@@ -425,7 +498,7 @@ export abstract class TextRenderer<
425
498
  abstract renderQuads(
426
499
  state: StateT,
427
500
  transform: Matrix3d,
428
- clippingRect: Rect | null,
501
+ clippingRect: RectWithValid,
429
502
  alpha: number,
430
503
  ): void;
431
504
  }
@@ -83,15 +83,23 @@ export class ImageTexture extends Texture {
83
83
  premultiplyAlpha,
84
84
  };
85
85
  }
86
- const response = await fetch(src);
87
- const blob = await response.blob();
88
- return {
89
- data: await createImageBitmap(blob, {
90
- premultiplyAlpha: premultiplyAlpha ? 'premultiply' : 'none',
91
- colorSpaceConversion: 'none',
92
- imageOrientation: 'none',
93
- }),
94
- };
86
+
87
+ if (this.txManager.imageWorkerManager.imageWorkersEnabled) {
88
+ return await this.txManager.imageWorkerManager.getImage(
89
+ src,
90
+ premultiplyAlpha,
91
+ );
92
+ } else {
93
+ const response = await fetch(src);
94
+ const blob = await response.blob();
95
+ return {
96
+ data: await createImageBitmap(blob, {
97
+ premultiplyAlpha: premultiplyAlpha ? 'premultiply' : 'none',
98
+ colorSpaceConversion: 'none',
99
+ imageOrientation: 'none',
100
+ }),
101
+ };
102
+ }
95
103
  }
96
104
 
97
105
  static override makeCacheKey(props: ImageTextureProps): string | false {