three-text 0.4.11 → 0.5.0

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 (94) hide show
  1. package/LICENSE +5 -660
  2. package/LICENSE_THIRD_PARTY +15 -49
  3. package/README.md +265 -44
  4. package/dist/index.cjs +3424 -3450
  5. package/dist/index.d.ts +163 -9
  6. package/dist/index.js +3420 -3451
  7. package/dist/index.min.cjs +718 -676
  8. package/dist/index.min.js +721 -679
  9. package/dist/index.umd.js +3561 -3579
  10. package/dist/index.umd.min.js +803 -756
  11. package/dist/p5/index.cjs +2738 -5
  12. package/dist/p5/index.js +2738 -5
  13. package/dist/patterns/index.js +0 -4
  14. package/dist/slug/index.cjs +380 -0
  15. package/dist/slug/index.d.ts +62 -0
  16. package/dist/slug/index.js +374 -0
  17. package/dist/three/index.cjs +50 -35
  18. package/dist/three/index.js +50 -35
  19. package/dist/three/react.cjs +5 -2
  20. package/dist/three/react.d.ts +66 -120
  21. package/dist/three/react.js +6 -3
  22. package/dist/types/core/Text.d.ts +3 -10
  23. package/dist/types/core/cache/sharedCaches.d.ts +2 -1
  24. package/dist/types/core/shaping/DrawCallbacks.d.ts +11 -3
  25. package/dist/types/core/shaping/TextShaper.d.ts +1 -5
  26. package/dist/types/core/types.d.ts +84 -0
  27. package/dist/types/index.d.ts +7 -3
  28. package/dist/types/{core/cache → mesh}/GlyphContourCollector.d.ts +4 -4
  29. package/dist/types/{core/cache → mesh}/GlyphGeometryBuilder.d.ts +5 -5
  30. package/dist/types/mesh/MeshGeometryBuilder.d.ts +18 -0
  31. package/dist/types/{core → mesh}/geometry/BoundaryClusterer.d.ts +1 -1
  32. package/dist/types/{core → mesh}/geometry/Extruder.d.ts +1 -1
  33. package/dist/types/{core → mesh}/geometry/PathOptimizer.d.ts +1 -1
  34. package/dist/types/{core → mesh}/geometry/Polygonizer.d.ts +1 -1
  35. package/dist/types/{core → mesh}/geometry/Tessellator.d.ts +1 -1
  36. package/dist/types/react/utils.d.ts +2 -0
  37. package/dist/types/vector/GlyphOutlineCollector.d.ts +25 -0
  38. package/dist/types/vector/GlyphVectorGeometryBuilder.d.ts +26 -0
  39. package/dist/types/vector/LoopBlinnGeometry.d.ts +68 -0
  40. package/dist/types/vector/index.d.ts +29 -0
  41. package/dist/types/vector/loopBlinnTSL.d.ts +11 -0
  42. package/dist/types/vector/react.d.ts +24 -0
  43. package/dist/types/vector/webgl/index.d.ts +7 -0
  44. package/dist/types/vector/webgpu/index.d.ts +11 -0
  45. package/dist/vector/index.cjs +1458 -0
  46. package/dist/vector/index.d.ts +122 -0
  47. package/dist/vector/index.js +1434 -0
  48. package/dist/vector/react.cjs +153 -0
  49. package/dist/vector/react.d.ts +317 -0
  50. package/dist/vector/react.js +132 -0
  51. package/dist/vector/types/slug-lib/src/SlugPacker.d.ts +17 -0
  52. package/dist/vector/types/slug-lib/src/WebGL2Renderer.d.ts +21 -0
  53. package/dist/vector/types/slug-lib/src/WebGPURenderer.d.ts +16 -0
  54. package/dist/vector/types/slug-lib/src/index.d.ts +15 -0
  55. package/dist/vector/types/slug-lib/src/shaderStrings.d.ts +9 -0
  56. package/dist/vector/types/slug-lib/src/types.d.ts +34 -0
  57. package/dist/vector/types/src/core/types.d.ts +381 -0
  58. package/dist/vector/types/src/hyphenation/HyphenationPatternLoader.d.ts +2 -0
  59. package/dist/vector/types/src/hyphenation/index.d.ts +7 -0
  60. package/dist/vector/types/src/hyphenation/types.d.ts +6 -0
  61. package/dist/vector/types/src/utils/Cache.d.ts +14 -0
  62. package/dist/vector/types/src/utils/vectors.d.ts +75 -0
  63. package/dist/vector/types/src/vector/VectorDataBuilder.d.ts +30 -0
  64. package/dist/vector/types/src/vector/VectorThreeAdapter.d.ts +27 -0
  65. package/dist/vector/types/src/vector/index.d.ts +15 -0
  66. package/dist/vector/webgl/index.cjs +229 -0
  67. package/dist/vector/webgl/index.d.ts +53 -0
  68. package/dist/vector/webgl/index.js +227 -0
  69. package/dist/vector/webgpu/index.cjs +321 -0
  70. package/dist/vector/webgpu/index.d.ts +57 -0
  71. package/dist/vector/webgpu/index.js +319 -0
  72. package/dist/webgl-vector/index.cjs +243 -0
  73. package/dist/webgl-vector/index.d.ts +34 -0
  74. package/dist/webgl-vector/index.js +241 -0
  75. package/dist/webgpu-vector/index.cjs +336 -0
  76. package/dist/webgpu-vector/index.d.ts +38 -0
  77. package/dist/webgpu-vector/index.js +334 -0
  78. package/package.json +49 -4
  79. package/dist/patterns/cs.cjs +0 -14
  80. package/dist/patterns/cs.d.ts +0 -28
  81. package/dist/patterns/cs.js +0 -14
  82. package/dist/patterns/cs.umd.js +0 -14
  83. package/dist/patterns/id.cjs +0 -14
  84. package/dist/patterns/id.d.ts +0 -28
  85. package/dist/patterns/id.js +0 -14
  86. package/dist/patterns/id.umd.js +0 -14
  87. package/dist/patterns/mk.cjs +0 -14
  88. package/dist/patterns/mk.d.ts +0 -28
  89. package/dist/patterns/mk.js +0 -14
  90. package/dist/patterns/mk.umd.js +0 -14
  91. package/dist/patterns/sr-cyrl.cjs +0 -14
  92. package/dist/patterns/sr-cyrl.d.ts +0 -28
  93. package/dist/patterns/sr-cyrl.js +0 -14
  94. package/dist/patterns/sr-cyrl.umd.js +0 -14
@@ -10,7 +10,6 @@ export const availablePatterns = [
10
10
  'bg',
11
11
  'bn',
12
12
  'ca',
13
- 'cs',
14
13
  'cy',
15
14
  'da',
16
15
  'de-1996',
@@ -34,7 +33,6 @@ export const availablePatterns = [
34
33
  'hu',
35
34
  'hy',
36
35
  'ia',
37
- 'id',
38
36
  'is',
39
37
  'it',
40
38
  'ka',
@@ -43,7 +41,6 @@ export const availablePatterns = [
43
41
  'la',
44
42
  'lt',
45
43
  'lv',
46
- 'mk',
47
44
  'ml',
48
45
  'mn-cyrl',
49
46
  'mr',
@@ -66,7 +63,6 @@ export const availablePatterns = [
66
63
  'sk',
67
64
  'sl',
68
65
  'sq',
69
- 'sr-cyrl',
70
66
  'sv',
71
67
  'ta',
72
68
  'te',
@@ -0,0 +1,380 @@
1
+ 'use strict';
2
+
3
+ var vertGLSL = "#version 300 es\n// ===================================================\n// GLSL 300 es port of the reference Slug vertex shader.\n// Original HLSL by Eric Lengyel, MIT License, Copyright 2017.\n// See: https://jcgt.org/published/0006/02/02/\n// ===================================================\n\nprecision highp float;\nprecision highp int;\n\n// Per-vertex attributes (5 x vec4, matching Slug reference layout)\nlayout(location = 0) in vec4 a_pos; // .xy = object-space position, .zw = outward normal\nlayout(location = 1) in vec4 a_tex; // .xy = em-space sample coords, .z = packed glyph loc, .w = packed band max + flags\nlayout(location = 2) in vec4 a_jac; // inverse Jacobian (2x2): (j00, j01, j10, j11)\nlayout(location = 3) in vec4 a_bnd; // (bandScaleX, bandScaleY, bandOffsetX, bandOffsetY)\nlayout(location = 4) in vec4 a_col; // vertex color RGBA\n\nuniform mat4 slug_matrix; // MVP matrix (rows as vec4s)\nuniform vec2 slug_viewport; // viewport dimensions in pixels\n\nout vec4 v_color;\nout vec2 v_texcoord;\nflat out vec4 v_banding;\nflat out ivec4 v_glyph;\n\nvoid SlugUnpack(vec4 tex, vec4 bnd, out vec4 vbnd, out ivec4 vgly) {\n uvec2 g = floatBitsToUint(tex.zw);\n vgly = ivec4(g.x & 0xFFFFu, g.x >> 16u, g.y & 0xFFFFu, g.y >> 16u);\n vbnd = bnd;\n}\n\nvec2 SlugDilate(vec4 pos, vec4 tex, vec4 jac, vec4 m0, vec4 m1, vec4 m3, vec2 dim, out vec2 vpos) {\n vec2 n = normalize(pos.zw);\n float s = dot(m3.xy, pos.xy) + m3.w;\n float t = dot(m3.xy, n);\n\n float u = (s * dot(m0.xy, n) - t * (dot(m0.xy, pos.xy) + m0.w)) * dim.x;\n float v = (s * dot(m1.xy, n) - t * (dot(m1.xy, pos.xy) + m1.w)) * dim.y;\n\n float s2 = s * s;\n float st = s * t;\n float uv = u * u + v * v;\n vec2 d = pos.zw * (s2 * (st + sqrt(uv)) / (uv - st * st));\n\n vpos = pos.xy + d;\n return vec2(tex.x + dot(d, jac.xy), tex.y + dot(d, jac.zw));\n}\n\nvoid main() {\n vec2 p;\n\n // Dynamic dilation: expand quad by a pixel to prevent edge clipping.\n v_texcoord = SlugDilate(a_pos, a_tex, a_jac,\n slug_matrix[0], slug_matrix[1], slug_matrix[3],\n slug_viewport, p);\n\n // MVP transform on dilated position.\n gl_Position.x = p.x * slug_matrix[0].x + p.y * slug_matrix[0].y + slug_matrix[0].w;\n gl_Position.y = p.x * slug_matrix[1].x + p.y * slug_matrix[1].y + slug_matrix[1].w;\n gl_Position.z = p.x * slug_matrix[2].x + p.y * slug_matrix[2].y + slug_matrix[2].w;\n gl_Position.w = p.x * slug_matrix[3].x + p.y * slug_matrix[3].y + slug_matrix[3].w;\n\n SlugUnpack(a_tex, a_bnd, v_banding, v_glyph);\n v_color = a_col;\n}\n";
4
+
5
+ var fragGLSL = "#version 300 es\n// ===================================================\n// GLSL 300 es port of the reference Slug pixel shader.\n// Original HLSL by Eric Lengyel, MIT License, Copyright 2017.\n// See: https://jcgt.org/published/0006/02/02/\n// ===================================================\n\nprecision highp float;\nprecision highp int;\n\n#define kLogBandTextureWidth 12\n\nin vec4 v_color;\nin vec2 v_texcoord;\nflat in vec4 v_banding;\nflat in ivec4 v_glyph;\n\nuniform sampler2D curveTexture; // RGBA32F control points\nuniform highp usampler2D bandTexture; // RGBA32UI band data\n\nlayout(location = 0) out vec4 outColor;\n\nuint CalcRootCode(float y1, float y2, float y3) {\n uint i1 = floatBitsToUint(y1) >> 31u;\n uint i2 = floatBitsToUint(y2) >> 30u;\n uint i3 = floatBitsToUint(y3) >> 29u;\n\n uint shift = (i2 & 2u) | (i1 & ~2u);\n shift = (i3 & 4u) | (shift & ~4u);\n\n return (0x2E74u >> shift) & 0x0101u;\n}\n\nvec2 SolveHorizPoly(vec4 p12, vec2 p3) {\n vec2 a = p12.xy - p12.zw * 2.0 + p3;\n vec2 b = p12.xy - p12.zw;\n float ra = 1.0 / a.y;\n float rb = 0.5 / b.y;\n\n float d = sqrt(max(b.y * b.y - a.y * p12.y, 0.0));\n float t1 = (b.y - d) * ra;\n float t2 = (b.y + d) * ra;\n\n if (abs(a.y) < 1.0 / 65536.0) t1 = t2 = p12.y * rb;\n\n return vec2((a.x * t1 - b.x * 2.0) * t1 + p12.x, (a.x * t2 - b.x * 2.0) * t2 + p12.x);\n}\n\nvec2 SolveVertPoly(vec4 p12, vec2 p3) {\n vec2 a = p12.xy - p12.zw * 2.0 + p3;\n vec2 b = p12.xy - p12.zw;\n float ra = 1.0 / a.x;\n float rb = 0.5 / b.x;\n\n float d = sqrt(max(b.x * b.x - a.x * p12.x, 0.0));\n float t1 = (b.x - d) * ra;\n float t2 = (b.x + d) * ra;\n\n if (abs(a.x) < 1.0 / 65536.0) t1 = t2 = p12.x * rb;\n\n return vec2((a.y * t1 - b.y * 2.0) * t1 + p12.y, (a.y * t2 - b.y * 2.0) * t2 + p12.y);\n}\n\nivec2 CalcBandLoc(ivec2 glyphLoc, uint offset) {\n ivec2 bandLoc = ivec2(glyphLoc.x + int(offset), glyphLoc.y);\n bandLoc.y += bandLoc.x >> kLogBandTextureWidth;\n bandLoc.x &= (1 << kLogBandTextureWidth) - 1;\n return bandLoc;\n}\n\nfloat CalcCoverage(float xcov, float ycov, float xwgt, float ywgt, int flags) {\n float coverage = max(abs(xcov * xwgt + ycov * ywgt) / max(xwgt + ywgt, 1.0 / 65536.0), min(abs(xcov), abs(ycov)));\n\n#if defined(SLUG_EVENODD)\n if ((flags & 0x1000) == 0) {\n#endif\n coverage = clamp(coverage, 0.0, 1.0);\n#if defined(SLUG_EVENODD)\n } else {\n coverage = 1.0 - abs(1.0 - fract(coverage * 0.5) * 2.0);\n }\n#endif\n\n#if defined(SLUG_WEIGHT)\n coverage = sqrt(coverage);\n#endif\n\n return coverage;\n}\n\nfloat SlugRender(vec2 renderCoord, vec4 bandTransform, ivec4 glyphData) {\n int curveIndex;\n\n vec2 emsPerPixel = fwidth(renderCoord);\n vec2 pixelsPerEm = 1.0 / emsPerPixel;\n\n ivec2 bandMax = glyphData.zw;\n bandMax.y &= 0x00FF;\n\n ivec2 bandIndex = clamp(ivec2(renderCoord * bandTransform.xy + bandTransform.zw), ivec2(0, 0), bandMax);\n ivec2 glyphLoc = glyphData.xy;\n\n float xcov = 0.0;\n float xwgt = 0.0;\n\n uvec2 hbandData = texelFetch(bandTexture, ivec2(glyphLoc.x + bandIndex.y, glyphLoc.y), 0).xy;\n ivec2 hbandLoc = CalcBandLoc(glyphLoc, hbandData.y);\n\n for (curveIndex = 0; curveIndex < int(hbandData.x); curveIndex++) {\n ivec2 curveLoc = ivec2(texelFetch(bandTexture, ivec2(hbandLoc.x + curveIndex, hbandLoc.y), 0).xy);\n\n vec4 p12 = texelFetch(curveTexture, curveLoc, 0) - vec4(renderCoord, renderCoord);\n vec2 p3 = texelFetch(curveTexture, ivec2(curveLoc.x + 1, curveLoc.y), 0).xy - renderCoord;\n\n if (max(max(p12.x, p12.z), p3.x) * pixelsPerEm.x < -0.5) break;\n\n uint code = CalcRootCode(p12.y, p12.w, p3.y);\n if (code != 0u) {\n vec2 r = SolveHorizPoly(p12, p3) * pixelsPerEm.x;\n\n if ((code & 1u) != 0u) {\n xcov += clamp(r.x + 0.5, 0.0, 1.0);\n xwgt = max(xwgt, clamp(1.0 - abs(r.x) * 2.0, 0.0, 1.0));\n }\n\n if (code > 1u) {\n xcov -= clamp(r.y + 0.5, 0.0, 1.0);\n xwgt = max(xwgt, clamp(1.0 - abs(r.y) * 2.0, 0.0, 1.0));\n }\n }\n }\n\n float ycov = 0.0;\n float ywgt = 0.0;\n\n uvec2 vbandData = texelFetch(bandTexture, ivec2(glyphLoc.x + bandMax.y + 1 + bandIndex.x, glyphLoc.y), 0).xy;\n ivec2 vbandLoc = CalcBandLoc(glyphLoc, vbandData.y);\n\n for (curveIndex = 0; curveIndex < int(vbandData.x); curveIndex++) {\n ivec2 curveLoc = ivec2(texelFetch(bandTexture, ivec2(vbandLoc.x + curveIndex, vbandLoc.y), 0).xy);\n vec4 p12 = texelFetch(curveTexture, curveLoc, 0) - vec4(renderCoord, renderCoord);\n vec2 p3 = texelFetch(curveTexture, ivec2(curveLoc.x + 1, curveLoc.y), 0).xy - renderCoord;\n\n if (max(max(p12.y, p12.w), p3.y) * pixelsPerEm.y < -0.5) break;\n\n uint code = CalcRootCode(p12.x, p12.z, p3.x);\n if (code != 0u) {\n vec2 r = SolveVertPoly(p12, p3) * pixelsPerEm.y;\n\n if ((code & 1u) != 0u) {\n ycov -= clamp(r.x + 0.5, 0.0, 1.0);\n ywgt = max(ywgt, clamp(1.0 - abs(r.x) * 2.0, 0.0, 1.0));\n }\n\n if (code > 1u) {\n ycov += clamp(r.y + 0.5, 0.0, 1.0);\n ywgt = max(ywgt, clamp(1.0 - abs(r.y) * 2.0, 0.0, 1.0));\n }\n }\n }\n\n return CalcCoverage(xcov, ycov, xwgt, ywgt, glyphData.w);\n}\n\nvoid main() {\n float coverage = SlugRender(v_texcoord, v_banding, v_glyph);\n outColor = v_color * coverage;\n}\n";
6
+
7
+ var vertWGSL = "// ===================================================\n// WGSL port of the reference Slug vertex shader.\n// Original HLSL by Eric Lengyel, MIT License, Copyright 2017.\n// See: https://jcgt.org/published/0006/02/02/\n// ===================================================\n\nstruct Uniforms {\n slug_matrix: mat4x4<f32>,\n slug_viewport: vec2<f32>,\n};\n\n@group(0) @binding(0) var<uniform> u: Uniforms;\n\nstruct VertexInput {\n @location(0) a_pos: vec4<f32>,\n @location(1) a_tex: vec4<f32>,\n @location(2) a_jac: vec4<f32>,\n @location(3) a_bnd: vec4<f32>,\n @location(4) a_col: vec4<f32>,\n};\n\nstruct VertexOutput {\n @builtin(position) position: vec4<f32>,\n @location(0) color: vec4<f32>,\n @location(1) texcoord: vec2<f32>,\n @location(2) @interpolate(flat) banding: vec4<f32>,\n @location(3) @interpolate(flat) glyph: vec4<i32>,\n};\n\nfn SlugUnpack(tex: vec4<f32>, bnd: vec4<f32>) -> VertexOutput {\n var out: VertexOutput;\n let g = bitcast<vec2<u32>>(tex.zw);\n out.glyph = vec4<i32>(\n i32(g.x & 0xFFFFu),\n i32(g.x >> 16u),\n i32(g.y & 0xFFFFu),\n i32(g.y >> 16u)\n );\n out.banding = bnd;\n return out;\n}\n\nfn SlugDilate(\n pos: vec4<f32>, tex: vec4<f32>, jac: vec4<f32>,\n m0: vec4<f32>, m1: vec4<f32>, m3: vec4<f32>,\n dim: vec2<f32>\n) -> vec4<f32> {\n // Returns vec4(dilated_pos.xy, new_texcoord.xy)\n let n = normalize(pos.zw);\n let s = dot(m3.xy, pos.xy) + m3.w;\n let t = dot(m3.xy, n);\n\n let u_val = (s * dot(m0.xy, n) - t * (dot(m0.xy, pos.xy) + m0.w)) * dim.x;\n let v_val = (s * dot(m1.xy, n) - t * (dot(m1.xy, pos.xy) + m1.w)) * dim.y;\n\n let s2 = s * s;\n let st = s * t;\n let uv = u_val * u_val + v_val * v_val;\n let d = pos.zw * (s2 * (st + sqrt(uv)) / (uv - st * st));\n\n let vpos = pos.xy + d;\n let vtex = vec2<f32>(tex.x + dot(d, jac.xy), tex.y + dot(d, jac.zw));\n return vec4<f32>(vpos, vtex);\n}\n\n@vertex\nfn vs_main(in: VertexInput) -> VertexOutput {\n let dilated = SlugDilate(\n in.a_pos, in.a_tex, in.a_jac,\n u.slug_matrix[0], u.slug_matrix[1], u.slug_matrix[3],\n u.slug_viewport\n );\n\n let p = dilated.xy;\n var out = SlugUnpack(in.a_tex, in.a_bnd);\n\n out.position = vec4<f32>(\n p.x * u.slug_matrix[0].x + p.y * u.slug_matrix[0].y + u.slug_matrix[0].w,\n p.x * u.slug_matrix[1].x + p.y * u.slug_matrix[1].y + u.slug_matrix[1].w,\n p.x * u.slug_matrix[2].x + p.y * u.slug_matrix[2].y + u.slug_matrix[2].w,\n p.x * u.slug_matrix[3].x + p.y * u.slug_matrix[3].y + u.slug_matrix[3].w\n );\n\n out.texcoord = dilated.zw;\n out.color = in.a_col;\n return out;\n}\n";
8
+
9
+ var fragWGSL = "// ===================================================\n// WGSL port of the reference Slug pixel shader.\n// Original HLSL by Eric Lengyel, MIT License, Copyright 2017.\n// See: https://jcgt.org/published/0006/02/02/\n// ===================================================\n\nconst kLogBandTextureWidth: u32 = 12u;\n\n@group(0) @binding(1) var curveTexture: texture_2d<f32>;\n@group(0) @binding(2) var bandTexture: texture_2d<u32>;\n\nstruct FragmentInput {\n @location(0) color: vec4<f32>,\n @location(1) texcoord: vec2<f32>,\n @location(2) @interpolate(flat) banding: vec4<f32>,\n @location(3) @interpolate(flat) glyph: vec4<i32>,\n};\n\nfn CalcRootCode(y1: f32, y2: f32, y3: f32) -> u32 {\n let i1 = bitcast<u32>(y1) >> 31u;\n let i2 = bitcast<u32>(y2) >> 30u;\n let i3 = bitcast<u32>(y3) >> 29u;\n\n var shift = (i2 & 2u) | (i1 & ~2u);\n shift = (i3 & 4u) | (shift & ~4u);\n\n return (0x2E74u >> shift) & 0x0101u;\n}\n\nfn SolveHorizPoly(p12: vec4<f32>, p3: vec2<f32>) -> vec2<f32> {\n let a = p12.xy - p12.zw * 2.0 + p3;\n let b = p12.xy - p12.zw;\n let ra = 1.0 / a.y;\n let rb = 0.5 / b.y;\n\n let d = sqrt(max(b.y * b.y - a.y * p12.y, 0.0));\n var t1 = (b.y - d) * ra;\n var t2 = (b.y + d) * ra;\n\n if (abs(a.y) < 1.0 / 65536.0) {\n t1 = p12.y * rb;\n t2 = t1;\n }\n\n return vec2<f32>(\n (a.x * t1 - b.x * 2.0) * t1 + p12.x,\n (a.x * t2 - b.x * 2.0) * t2 + p12.x\n );\n}\n\nfn SolveVertPoly(p12: vec4<f32>, p3: vec2<f32>) -> vec2<f32> {\n let a = p12.xy - p12.zw * 2.0 + p3;\n let b = p12.xy - p12.zw;\n let ra = 1.0 / a.x;\n let rb = 0.5 / b.x;\n\n let d = sqrt(max(b.x * b.x - a.x * p12.x, 0.0));\n var t1 = (b.x - d) * ra;\n var t2 = (b.x + d) * ra;\n\n if (abs(a.x) < 1.0 / 65536.0) {\n t1 = p12.x * rb;\n t2 = t1;\n }\n\n return vec2<f32>(\n (a.y * t1 - b.y * 2.0) * t1 + p12.y,\n (a.y * t2 - b.y * 2.0) * t2 + p12.y\n );\n}\n\nfn CalcBandLoc(glyphLoc: vec2<i32>, offset: u32) -> vec2<i32> {\n var bandLoc = vec2<i32>(glyphLoc.x + i32(offset), glyphLoc.y);\n bandLoc.y += bandLoc.x >> i32(kLogBandTextureWidth);\n bandLoc.x &= (1 << i32(kLogBandTextureWidth)) - 1;\n return bandLoc;\n}\n\nfn CalcCoverage(xcov: f32, ycov: f32, xwgt: f32, ywgt: f32) -> f32 {\n var coverage = max(\n abs(xcov * xwgt + ycov * ywgt) / max(xwgt + ywgt, 1.0 / 65536.0),\n min(abs(xcov), abs(ycov))\n );\n coverage = clamp(coverage, 0.0, 1.0);\n return coverage;\n}\n\nfn SlugRender(renderCoord: vec2<f32>, bandTransform: vec4<f32>, glyphData: vec4<i32>) -> f32 {\n let emsPerPixel = fwidth(renderCoord);\n let pixelsPerEm = 1.0 / emsPerPixel;\n\n var bandMax = glyphData.zw;\n bandMax.y &= 0x00FF;\n\n let bandIndex = clamp(\n vec2<i32>(renderCoord * bandTransform.xy + bandTransform.zw),\n vec2<i32>(0, 0),\n bandMax\n );\n let glyphLoc = glyphData.xy;\n\n var xcov = 0.0;\n var xwgt = 0.0;\n\n let hbandData = textureLoad(bandTexture, vec2<i32>(glyphLoc.x + bandIndex.y, glyphLoc.y), 0).xy;\n let hbandLoc = CalcBandLoc(glyphLoc, hbandData.y);\n\n for (var ci = 0; ci < i32(hbandData.x); ci++) {\n let curveLoc = vec2<i32>(textureLoad(bandTexture, vec2<i32>(hbandLoc.x + ci, hbandLoc.y), 0).xy);\n\n let p12 = textureLoad(curveTexture, curveLoc, 0) - vec4<f32>(renderCoord, renderCoord);\n let p3 = textureLoad(curveTexture, vec2<i32>(curveLoc.x + 1, curveLoc.y), 0).xy - renderCoord;\n\n if (max(max(p12.x, p12.z), p3.x) * pixelsPerEm.x < -0.5) { break; }\n\n let code = CalcRootCode(p12.y, p12.w, p3.y);\n if (code != 0u) {\n let r = SolveHorizPoly(p12, p3) * pixelsPerEm.x;\n\n if ((code & 1u) != 0u) {\n xcov += clamp(r.x + 0.5, 0.0, 1.0);\n xwgt = max(xwgt, clamp(1.0 - abs(r.x) * 2.0, 0.0, 1.0));\n }\n if (code > 1u) {\n xcov -= clamp(r.y + 0.5, 0.0, 1.0);\n xwgt = max(xwgt, clamp(1.0 - abs(r.y) * 2.0, 0.0, 1.0));\n }\n }\n }\n\n var ycov = 0.0;\n var ywgt = 0.0;\n\n let vbandData = textureLoad(bandTexture, vec2<i32>(glyphLoc.x + bandMax.y + 1 + bandIndex.x, glyphLoc.y), 0).xy;\n let vbandLoc = CalcBandLoc(glyphLoc, vbandData.y);\n\n for (var ci = 0; ci < i32(vbandData.x); ci++) {\n let curveLoc = vec2<i32>(textureLoad(bandTexture, vec2<i32>(vbandLoc.x + ci, vbandLoc.y), 0).xy);\n let p12 = textureLoad(curveTexture, curveLoc, 0) - vec4<f32>(renderCoord, renderCoord);\n let p3 = textureLoad(curveTexture, vec2<i32>(curveLoc.x + 1, curveLoc.y), 0).xy - renderCoord;\n\n if (max(max(p12.y, p12.w), p3.y) * pixelsPerEm.y < -0.5) { break; }\n\n let code = CalcRootCode(p12.x, p12.z, p3.x);\n if (code != 0u) {\n let r = SolveVertPoly(p12, p3) * pixelsPerEm.y;\n\n if ((code & 1u) != 0u) {\n ycov -= clamp(r.x + 0.5, 0.0, 1.0);\n ywgt = max(ywgt, clamp(1.0 - abs(r.x) * 2.0, 0.0, 1.0));\n }\n if (code > 1u) {\n ycov += clamp(r.y + 0.5, 0.0, 1.0);\n ywgt = max(ywgt, clamp(1.0 - abs(r.y) * 2.0, 0.0, 1.0));\n }\n }\n }\n\n return CalcCoverage(xcov, ycov, xwgt, ywgt);\n}\n\n@fragment\nfn fs_main(in: FragmentInput) -> @location(0) vec4<f32> {\n let coverage = SlugRender(in.texcoord, in.banding, in.glyph);\n return in.color * coverage;\n}\n";
10
+
11
+ /**
12
+ * Slug shader source re-exports.
13
+ * The .glsl/.wgsl files are the single source of truth — imported as strings
14
+ * at build time via the glslPlugin in rollup.config.js.
15
+ */
16
+ // @ts-ignore — resolved by rollup glslPlugin
17
+ const vertexShaderGLSL300 = vertGLSL;
18
+ const fragmentShaderGLSL300 = fragGLSL;
19
+ const vertexShaderWGSL = vertWGSL;
20
+ const fragmentShaderWGSL = fragWGSL;
21
+
22
+ /**
23
+ * CPU-side data packer for the Slug algorithm.
24
+ * Faithful to Eric Lengyel's reference layout (MIT License, 2017).
25
+ *
26
+ * Takes generic quadratic Bezier shapes (not text-specific) and produces
27
+ * GPU-ready packed textures + vertex attribute buffers.
28
+ */
29
+ const TEX_WIDTH = 4096;
30
+ const LOG_TEX_WIDTH = 12;
31
+ // Float ↔ Uint32 reinterpretation helpers
32
+ const _f32 = new Float32Array(1);
33
+ const _u32 = new Uint32Array(_f32.buffer);
34
+ function uintAsFloat(u) {
35
+ _u32[0] = u;
36
+ return _f32[0];
37
+ }
38
+ /**
39
+ * Pack an array of shapes into Slug's GPU data layout.
40
+ *
41
+ * Each shape is a closed region defined by quadratic Bezier curves.
42
+ * Returns textures + vertex buffers ready for GPU upload.
43
+ */
44
+ function packSlugData(shapes, options) {
45
+ const bandCount = options?.bandCount ?? 16;
46
+ const evenOdd = options?.evenOdd ?? false;
47
+ // Phase 1: Pack all curves into curveTexture
48
+ const allCurves = [];
49
+ // Estimate max texels needed
50
+ let totalCurves = 0;
51
+ for (const shape of shapes) {
52
+ totalCurves += shape.curves.length;
53
+ }
54
+ const curveTexHeight = Math.ceil((totalCurves * 2) / TEX_WIDTH) + 1;
55
+ const curveData = new Float32Array(TEX_WIDTH * curveTexHeight * 4);
56
+ let curveX = 0;
57
+ let curveY = 0;
58
+ for (const shape of shapes) {
59
+ const entries = [];
60
+ for (const curve of shape.curves) {
61
+ // Don't let a curve span across row boundary (needs 2 consecutive texels)
62
+ if (curveX >= TEX_WIDTH - 1) {
63
+ curveX = 0;
64
+ curveY++;
65
+ }
66
+ const base = (curveY * TEX_WIDTH + curveX) * 4;
67
+ curveData[base + 0] = curve.p1[0];
68
+ curveData[base + 1] = curve.p1[1];
69
+ curveData[base + 2] = curve.p2[0];
70
+ curveData[base + 3] = curve.p2[1];
71
+ const base2 = base + 4;
72
+ curveData[base2 + 0] = curve.p3[0];
73
+ curveData[base2 + 1] = curve.p3[1];
74
+ const minX = Math.min(curve.p1[0], curve.p2[0], curve.p3[0]);
75
+ const minY = Math.min(curve.p1[1], curve.p2[1], curve.p3[1]);
76
+ const maxX = Math.max(curve.p1[0], curve.p2[0], curve.p3[0]);
77
+ const maxY = Math.max(curve.p1[1], curve.p2[1], curve.p3[1]);
78
+ entries.push({
79
+ p1x: curve.p1[0], p1y: curve.p1[1],
80
+ p2x: curve.p2[0], p2y: curve.p2[1],
81
+ p3x: curve.p3[0], p3y: curve.p3[1],
82
+ minX, minY, maxX, maxY,
83
+ curveTexX: curveX,
84
+ curveTexY: curveY
85
+ });
86
+ curveX += 2;
87
+ }
88
+ allCurves.push(entries);
89
+ }
90
+ const actualCurveTexHeight = curveY + 1;
91
+ // Phase 2: Build band data for each shape and pack into bandTexture
92
+ // Layout per shape in bandTexture (relative to glyphLoc):
93
+ // [0 .. hBandMax] : h-band headers
94
+ // [hBandMax+1 .. hBandMax+1+vBandMax] : v-band headers
95
+ // [hBandMax+vBandMax+2 .. ] : curve index lists
96
+ // First pass: compute total band texels needed
97
+ const shapeBandData = [];
98
+ let totalBandTexels = 0;
99
+ for (let si = 0; si < shapes.length; si++) {
100
+ const shape = shapes[si];
101
+ const curves = allCurves[si];
102
+ if (curves.length === 0) {
103
+ shapeBandData.push({
104
+ hBands: [], vBands: [], hLists: [], vLists: [],
105
+ totalTexels: 0, bandMaxX: 0, bandMaxY: 0
106
+ });
107
+ continue;
108
+ }
109
+ const [bMinX, bMinY, bMaxX, bMaxY] = shape.bounds;
110
+ const w = bMaxX - bMinX;
111
+ const h = bMaxY - bMinY;
112
+ const hBandCount = Math.min(bandCount, 255); // max 255 (fits in 8 bits)
113
+ const vBandCount = Math.min(bandCount, 255);
114
+ const bandMaxY = hBandCount - 1;
115
+ const bandMaxX = vBandCount - 1;
116
+ // Build horizontal bands (partition y-axis)
117
+ const hBands = [];
118
+ const hLists = [];
119
+ const bandH = h / hBandCount;
120
+ for (let bi = 0; bi < hBandCount; bi++) {
121
+ const bandMinY = bMinY + bi * bandH;
122
+ const bandMaxYCoord = bandMinY + bandH;
123
+ // Collect curves whose y-range overlaps this band
124
+ const list = [];
125
+ for (const c of curves) {
126
+ if (c.maxY >= bandMinY && c.minY <= bandMaxYCoord) {
127
+ list.push({ curve: c, sortKey: c.maxX });
128
+ }
129
+ }
130
+ // Sort by descending max-x for early exit
131
+ list.sort((a, b) => b.sortKey - a.sortKey);
132
+ const flatList = [];
133
+ for (const item of list) {
134
+ flatList.push(item.curve.curveTexX, item.curve.curveTexY);
135
+ }
136
+ hBands.push({ curveCount: list.length, listOffset: 0 });
137
+ hLists.push(flatList);
138
+ }
139
+ // Build vertical bands (partition x-axis)
140
+ const vBands = [];
141
+ const vLists = [];
142
+ const bandW = w / vBandCount;
143
+ for (let bi = 0; bi < vBandCount; bi++) {
144
+ const bandMinX = bMinX + bi * bandW;
145
+ const bandMaxXCoord = bandMinX + bandW;
146
+ const list = [];
147
+ for (const c of curves) {
148
+ if (c.maxX >= bandMinX && c.minX <= bandMaxXCoord) {
149
+ list.push({ curve: c, sortKey: c.maxY });
150
+ }
151
+ }
152
+ // Sort by descending max-y for early exit
153
+ list.sort((a, b) => b.sortKey - a.sortKey);
154
+ const flatList = [];
155
+ for (const item of list) {
156
+ flatList.push(item.curve.curveTexX, item.curve.curveTexY);
157
+ }
158
+ vBands.push({ curveCount: list.length, listOffset: 0 });
159
+ vLists.push(flatList);
160
+ }
161
+ // Total texels for this shape: band headers + curve lists
162
+ const headerTexels = hBandCount + vBandCount;
163
+ let listTexels = 0;
164
+ for (const l of hLists)
165
+ listTexels += l.length / 2;
166
+ for (const l of vLists)
167
+ listTexels += l.length / 2;
168
+ const total = headerTexels + listTexels;
169
+ shapeBandData.push({
170
+ hBands, vBands, hLists, vLists,
171
+ totalTexels: total, bandMaxX, bandMaxY
172
+ });
173
+ totalBandTexels += total;
174
+ }
175
+ // Allocate bandTexture
176
+ const bandTexHeight = Math.max(1, Math.ceil(totalBandTexels / TEX_WIDTH) + shapes.length);
177
+ const bandData = new Uint32Array(TEX_WIDTH * bandTexHeight * 4);
178
+ // Pack band data per shape
179
+ let bandX = 0;
180
+ let bandY = 0;
181
+ const glyphLocs = [];
182
+ for (let si = 0; si < shapes.length; si++) {
183
+ const sd = shapeBandData[si];
184
+ if (sd.totalTexels === 0) {
185
+ glyphLocs.push({ x: 0, y: 0 });
186
+ continue;
187
+ }
188
+ // Ensure glyph data doesn't start too close to row end
189
+ // (need at least headerTexels contiguous... actually wrapping is handled by CalcBandLoc)
190
+ // But the initial band header reads don't use CalcBandLoc, so glyphLoc.x + bandMax.y + 1 + bandMaxX
191
+ // must be reachable. CalcBandLoc handles wrapping for curve lists.
192
+ // To be safe, start each glyph at the beginning of a row if remaining space is tight.
193
+ const minContiguous = sd.hBands.length + sd.vBands.length;
194
+ if (bandX + minContiguous > TEX_WIDTH) {
195
+ bandX = 0;
196
+ bandY++;
197
+ }
198
+ const glyphLocX = bandX;
199
+ const glyphLocY = bandY;
200
+ glyphLocs.push({ x: glyphLocX, y: glyphLocY });
201
+ // Curve lists start after all headers
202
+ let listStartOffset = sd.hBands.length + sd.vBands.length;
203
+ // Assign list offsets for h-bands
204
+ for (let bi = 0; bi < sd.hBands.length; bi++) {
205
+ sd.hBands[bi].listOffset = listStartOffset;
206
+ listStartOffset += sd.hLists[bi].length / 2;
207
+ }
208
+ // Assign list offsets for v-bands
209
+ for (let bi = 0; bi < sd.vBands.length; bi++) {
210
+ sd.vBands[bi].listOffset = listStartOffset;
211
+ listStartOffset += sd.vLists[bi].length / 2;
212
+ }
213
+ // Write h-band headers
214
+ for (let bi = 0; bi < sd.hBands.length; bi++) {
215
+ const tx = glyphLocX + bi;
216
+ const ty = glyphLocY;
217
+ const idx = (ty * TEX_WIDTH + tx) * 4;
218
+ bandData[idx + 0] = sd.hBands[bi].curveCount;
219
+ bandData[idx + 1] = sd.hBands[bi].listOffset;
220
+ bandData[idx + 2] = 0;
221
+ bandData[idx + 3] = 0;
222
+ }
223
+ // Write v-band headers (after h-bands)
224
+ const vBandStart = glyphLocX + sd.hBands.length;
225
+ for (let bi = 0; bi < sd.vBands.length; bi++) {
226
+ const tx = vBandStart + bi;
227
+ const ty = glyphLocY;
228
+ const idx = (ty * TEX_WIDTH + tx) * 4;
229
+ bandData[idx + 0] = sd.vBands[bi].curveCount;
230
+ bandData[idx + 1] = sd.vBands[bi].listOffset;
231
+ bandData[idx + 2] = 0;
232
+ bandData[idx + 3] = 0;
233
+ }
234
+ // Write curve lists using CalcBandLoc-style wrapping
235
+ const writeBandLoc = (offset) => {
236
+ let bx = glyphLocX + offset;
237
+ let by = glyphLocY;
238
+ by += bx >> LOG_TEX_WIDTH;
239
+ bx &= (1 << LOG_TEX_WIDTH) - 1;
240
+ return { x: bx, y: by };
241
+ };
242
+ // Write h-band curve lists
243
+ for (let bi = 0; bi < sd.hBands.length; bi++) {
244
+ const list = sd.hLists[bi];
245
+ const baseOffset = sd.hBands[bi].listOffset;
246
+ for (let ci = 0; ci < list.length; ci += 2) {
247
+ const loc = writeBandLoc(baseOffset + ci / 2);
248
+ const idx = (loc.y * TEX_WIDTH + loc.x) * 4;
249
+ bandData[idx + 0] = list[ci]; // curveTexX
250
+ bandData[idx + 1] = list[ci + 1]; // curveTexY
251
+ bandData[idx + 2] = 0;
252
+ bandData[idx + 3] = 0;
253
+ }
254
+ }
255
+ // Write v-band curve lists
256
+ for (let bi = 0; bi < sd.vBands.length; bi++) {
257
+ const list = sd.vLists[bi];
258
+ const baseOffset = sd.vBands[bi].listOffset;
259
+ for (let ci = 0; ci < list.length; ci += 2) {
260
+ const loc = writeBandLoc(baseOffset + ci / 2);
261
+ const idx = (loc.y * TEX_WIDTH + loc.x) * 4;
262
+ bandData[idx + 0] = list[ci];
263
+ bandData[idx + 1] = list[ci + 1];
264
+ bandData[idx + 2] = 0;
265
+ bandData[idx + 3] = 0;
266
+ }
267
+ }
268
+ // Advance band cursor past this shape's data
269
+ const totalForShape = listStartOffset;
270
+ const endLoc = writeBandLoc(totalForShape);
271
+ bandX = endLoc.x;
272
+ bandY = endLoc.y;
273
+ }
274
+ const actualBandTexHeight = bandY + 1;
275
+ // Phase 3: Build vertex attributes
276
+ // 5 attribs x 4 floats x 4 vertices per shape = 80 floats per shape
277
+ const FLOATS_PER_VERTEX = 20; // 5 attribs * 4 components
278
+ const VERTS_PER_SHAPE = 4;
279
+ const vertices = new Float32Array(shapes.length * VERTS_PER_SHAPE * FLOATS_PER_VERTEX);
280
+ const indices = new Uint16Array(shapes.length * 6);
281
+ // Corner normals (outward-pointing, un-normalized — SlugDilate normalizes)
282
+ const cornerNormals = [
283
+ [-1, -1], // bottom-left
284
+ [1, -1], // bottom-right
285
+ [1, 1], // top-right
286
+ [-1, 1], // top-left
287
+ ];
288
+ for (let si = 0; si < shapes.length; si++) {
289
+ const shape = shapes[si];
290
+ const sd = shapeBandData[si];
291
+ const glyph = glyphLocs[si];
292
+ const [bMinX, bMinY, bMaxX, bMaxY] = shape.bounds;
293
+ const w = bMaxX - bMinX;
294
+ const h = bMaxY - bMinY;
295
+ // Corner positions in object-space
296
+ const corners = [
297
+ [bMinX, bMinY],
298
+ [bMaxX, bMinY],
299
+ [bMaxX, bMaxY],
300
+ [bMinX, bMaxY],
301
+ ];
302
+ // Em-space sample coords at corners (same as object-space for 1:1 mapping)
303
+ const emCorners = [
304
+ [bMinX, bMinY],
305
+ [bMaxX, bMinY],
306
+ [bMaxX, bMaxY],
307
+ [bMinX, bMaxY],
308
+ ];
309
+ // Pack tex.z: glyph location in band texture
310
+ const texZ = uintAsFloat((glyph.x & 0xFFFF) | ((glyph.y & 0xFFFF) << 16));
311
+ // Pack tex.w: band max + flags
312
+ let texWBits = (sd.bandMaxX & 0xFF) | ((sd.bandMaxY & 0xFF) << 16);
313
+ if (evenOdd)
314
+ texWBits |= 0x10000000; // E flag at bit 28
315
+ const texW = uintAsFloat(texWBits);
316
+ // Band transform: scale and offset to map em-coords to band indices
317
+ const bandScaleX = w > 0 ? sd.vBands.length / w : 0;
318
+ const bandScaleY = h > 0 ? sd.hBands.length / h : 0;
319
+ const bandOffsetX = -bMinX * bandScaleX;
320
+ const bandOffsetY = -bMinY * bandScaleY;
321
+ for (let vi = 0; vi < 4; vi++) {
322
+ const base = (si * 4 + vi) * FLOATS_PER_VERTEX;
323
+ // pos: .xy = position, .zw = normal
324
+ vertices[base + 0] = corners[vi][0];
325
+ vertices[base + 1] = corners[vi][1];
326
+ vertices[base + 2] = cornerNormals[vi][0];
327
+ vertices[base + 3] = cornerNormals[vi][1];
328
+ // tex: .xy = em-space coords, .z = packed glyph loc, .w = packed band max
329
+ vertices[base + 4] = emCorners[vi][0];
330
+ vertices[base + 5] = emCorners[vi][1];
331
+ vertices[base + 6] = texZ;
332
+ vertices[base + 7] = texW;
333
+ // jac: identity Jacobian (em-space = object-space)
334
+ vertices[base + 8] = 1.0;
335
+ vertices[base + 9] = 0.0;
336
+ vertices[base + 10] = 0.0;
337
+ vertices[base + 11] = 1.0;
338
+ // bnd: band scale and offset
339
+ vertices[base + 12] = bandScaleX;
340
+ vertices[base + 13] = bandScaleY;
341
+ vertices[base + 14] = bandOffsetX;
342
+ vertices[base + 15] = bandOffsetY;
343
+ // col: white with full alpha (caller overrides via uniform or attribute)
344
+ vertices[base + 16] = 1.0;
345
+ vertices[base + 17] = 1.0;
346
+ vertices[base + 18] = 1.0;
347
+ vertices[base + 19] = 1.0;
348
+ }
349
+ // Indices: two triangles per quad
350
+ const vBase = si * 4;
351
+ const iBase = si * 6;
352
+ indices[iBase + 0] = vBase + 0;
353
+ indices[iBase + 1] = vBase + 1;
354
+ indices[iBase + 2] = vBase + 2;
355
+ indices[iBase + 3] = vBase + 0;
356
+ indices[iBase + 4] = vBase + 2;
357
+ indices[iBase + 5] = vBase + 3;
358
+ }
359
+ return {
360
+ curveTexture: {
361
+ data: curveData.subarray(0, TEX_WIDTH * actualCurveTexHeight * 4),
362
+ width: TEX_WIDTH,
363
+ height: actualCurveTexHeight
364
+ },
365
+ bandTexture: {
366
+ data: bandData.subarray(0, TEX_WIDTH * actualBandTexHeight * 4),
367
+ width: TEX_WIDTH,
368
+ height: actualBandTexHeight
369
+ },
370
+ vertices,
371
+ indices,
372
+ shapeCount: shapes.length
373
+ };
374
+ }
375
+
376
+ exports.fragmentShaderGLSL300 = fragmentShaderGLSL300;
377
+ exports.fragmentShaderWGSL = fragmentShaderWGSL;
378
+ exports.packSlugData = packSlugData;
379
+ exports.vertexShaderGLSL300 = vertexShaderGLSL300;
380
+ exports.vertexShaderWGSL = vertexShaderWGSL;
@@ -0,0 +1,62 @@
1
+ /**
2
+ * Pure Slug algorithm types — no dependency on three-text internals.
3
+ * Based on Eric Lengyel's reference implementation (MIT License, 2017).
4
+ */
5
+ interface QuadCurve {
6
+ p1: [number, number];
7
+ p2: [number, number];
8
+ p3: [number, number];
9
+ }
10
+ interface SlugShape {
11
+ curves: QuadCurve[];
12
+ bounds: [number, number, number, number];
13
+ }
14
+ interface SlugPackedTexture {
15
+ data: Float32Array | Uint32Array;
16
+ width: number;
17
+ height: number;
18
+ }
19
+ interface SlugGPUData {
20
+ curveTexture: SlugPackedTexture & {
21
+ data: Float32Array;
22
+ };
23
+ bandTexture: SlugPackedTexture & {
24
+ data: Uint32Array;
25
+ };
26
+ /** 5 attribs x 4 components x 4 verts per shape, tightly packed per-shape */
27
+ vertices: Float32Array;
28
+ indices: Uint16Array;
29
+ shapeCount: number;
30
+ }
31
+ interface SlugPackOptions {
32
+ bandCount?: number;
33
+ evenOdd?: boolean;
34
+ }
35
+
36
+ /**
37
+ * Slug shader source re-exports.
38
+ * The .glsl/.wgsl files are the single source of truth — imported as strings
39
+ * at build time via the glslPlugin in rollup.config.js.
40
+ */
41
+ declare const vertexShaderGLSL300: string;
42
+ declare const fragmentShaderGLSL300: string;
43
+ declare const vertexShaderWGSL: string;
44
+ declare const fragmentShaderWGSL: string;
45
+
46
+ /**
47
+ * CPU-side data packer for the Slug algorithm.
48
+ * Faithful to Eric Lengyel's reference layout (MIT License, 2017).
49
+ *
50
+ * Takes generic quadratic Bezier shapes (not text-specific) and produces
51
+ * GPU-ready packed textures + vertex attribute buffers.
52
+ */
53
+
54
+ /**
55
+ * Pack an array of shapes into Slug's GPU data layout.
56
+ *
57
+ * Each shape is a closed region defined by quadratic Bezier curves.
58
+ * Returns textures + vertex buffers ready for GPU upload.
59
+ */
60
+ declare function packSlugData(shapes: SlugShape[], options?: SlugPackOptions): SlugGPUData;
61
+
62
+ export { QuadCurve, SlugGPUData, SlugPackOptions, SlugPackedTexture, SlugShape, fragmentShaderGLSL300, fragmentShaderWGSL, packSlugData, vertexShaderGLSL300, vertexShaderWGSL };