asciify-engine 1.0.25 → 1.0.27

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.
package/dist/index.d.cts CHANGED
@@ -121,20 +121,6 @@ declare function renderFrameToCanvas(ctx: CanvasRenderingContext2D, frame: Ascii
121
121
  intensity?: number;
122
122
  } | null): void;
123
123
 
124
- /**
125
- * Embed code generation — serializes ASCII frames into self-contained
126
- * HTML snippets that replay via the CDN embed runtime.
127
- */
128
-
129
- /**
130
- * Generate a static single-frame embed snippet.
131
- */
132
- declare function generateEmbedCode(frame: AsciiFrame, options: AsciiOptions, width: number, height: number): string;
133
- /**
134
- * Generate an animated multi-frame embed snippet (GIF / video).
135
- */
136
- declare function generateAnimatedEmbedCode(frames: AsciiFrame[], options: AsciiOptions, fps: number, width: number, height: number): string;
137
-
138
124
  /**
139
125
  * Simple one-call asciify API.
140
126
  * Wraps imageToAsciiFrame + renderFrameToCanvas behind easy-to-use helpers.
@@ -606,6 +592,124 @@ declare function asciiText(source: HTMLImageElement | HTMLVideoElement | HTMLCan
606
592
  */
607
593
  declare function asciiTextAnsi(source: HTMLImageElement | HTMLVideoElement | HTMLCanvasElement, options?: Partial<AsciiOptions>, targetWidth?: number, targetHeight?: number): string;
608
594
 
595
+ /**
596
+ * text-frame.ts — Build and render ASCII frames from tiling text patterns.
597
+ *
598
+ * Enables interactive text backgrounds with the full hover-effect system
599
+ * (spotlight, magnify, repel, glow, colorShift, …) without needing an image
600
+ * source.
601
+ *
602
+ * @example — basic usage
603
+ * ```ts
604
+ * import { renderTextBackground } from 'asciify-engine';
605
+ *
606
+ * function tick(ctx, w, h, mousePos) {
607
+ * renderTextBackground(ctx, w, h, 'asciify·engine·v1·', {
608
+ * hoverEffect: 'spotlight',
609
+ * hoverColor: '#d4ff00',
610
+ * }, mousePos);
611
+ * requestAnimationFrame(() => tick(ctx, w, h, mousePos));
612
+ * }
613
+ * ```
614
+ *
615
+ * @example — build the frame yourself and pass it to renderFrameToCanvas
616
+ * ```ts
617
+ * import { buildTextFrame, renderFrameToCanvas, DEFAULT_OPTIONS } from 'asciify-engine';
618
+ *
619
+ * const frame = buildTextFrame('hello world · ', 80, 24);
620
+ * renderFrameToCanvas(ctx, frame, {
621
+ * ...DEFAULT_OPTIONS,
622
+ * hoverEffect: 'repel',
623
+ * hoverStrength: 0.9,
624
+ * hoverColor: '#a0e8ff',
625
+ * }, width, height, 0, mousePos);
626
+ * ```
627
+ */
628
+
629
+ interface TextBackgroundOptions {
630
+ /**
631
+ * Character size in pixels.
632
+ * Controls the grid density: smaller → more cells, finer text.
633
+ * @default 10
634
+ */
635
+ fontSize?: number;
636
+ /**
637
+ * Line-height multiplier applied on top of `fontSize` to derive row height.
638
+ * Matches the default monospace aspect ratio used by the renderer.
639
+ * @default 1.6
640
+ */
641
+ lineHeight?: number;
642
+ /**
643
+ * Base colour for the text cells (inactive state).
644
+ * Accepts any CSS hex or rgb string.
645
+ * @default '#505050'
646
+ */
647
+ color?: string;
648
+ /**
649
+ * Base alpha for the text cells, 0–255.
650
+ * @default 100
651
+ */
652
+ opacity?: number;
653
+ /**
654
+ * Which hover effect to activate when `hoverPos` is supplied.
655
+ * @default 'spotlight'
656
+ */
657
+ hoverEffect?: HoverEffect;
658
+ /**
659
+ * Intensity of the hover distortion / glow, 0–1.
660
+ * @default 0.85
661
+ */
662
+ hoverStrength?: number;
663
+ /**
664
+ * Normalised radius of the hover influence zone, 0–1.
665
+ * @default 0.18
666
+ */
667
+ hoverRadius?: number;
668
+ /**
669
+ * Accent colour applied by the hover effect.
670
+ * @default '#d4ff00'
671
+ */
672
+ hoverColor?: string;
673
+ }
674
+ /**
675
+ * Build an `AsciiFrame` filled with a tiling text pattern.
676
+ *
677
+ * The `text` string is repeated (wrapping at column boundaries) across every
678
+ * cell of the `cols × rows` grid. Each cell carries the supplied base colour
679
+ * and opacity as `{r, g, b, a}` values.
680
+ *
681
+ * The returned frame can be passed directly to `renderFrameToCanvas` with any
682
+ * `AsciiOptions` including hover effects.
683
+ *
684
+ * @param text - Pattern string to tile across the grid (e.g. `'hello · '`)
685
+ * @param cols - Number of character columns
686
+ * @param rows - Number of character rows
687
+ * @param color - Base RGB colour string for the cells (default: `'#505050'`)
688
+ * @param opacity - Base alpha 0–255 (default: `100`)
689
+ */
690
+ declare function buildTextFrame(text: string, cols: number, rows: number, color?: string, opacity?: number): AsciiFrame;
691
+ /**
692
+ * All-in-one: build a tiling text grid and render it to a canvas with the
693
+ * full hover-effect system (spotlight, magnify, repel, glow, colorShift, …).
694
+ *
695
+ * Call this inside a `requestAnimationFrame` loop, passing updated `hoverPos`
696
+ * each frame to get smooth interactive effects.
697
+ *
698
+ * @param ctx - 2D rendering context of the target canvas
699
+ * @param width - Canvas logical width in pixels
700
+ * @param height - Canvas logical height in pixels
701
+ * @param text - Pattern string to tile (e.g. `'asciify·engine·v1·'`)
702
+ * @param options - {@link TextBackgroundOptions}
703
+ * @param hoverPos - Normalised mouse position `{x, y}` in 0–1 range,
704
+ * optionally with an `intensity` multiplier (0–1).
705
+ * Pass `null` or omit to render without hover.
706
+ */
707
+ declare function renderTextBackground(ctx: CanvasRenderingContext2D, width: number, height: number, text: string, options?: TextBackgroundOptions, hoverPos?: {
708
+ x: number;
709
+ y: number;
710
+ intensity?: number;
711
+ } | null): void;
712
+
609
713
  /**
610
714
  * record() — capture a rolling frame buffer from a running ASCII canvas
611
715
  * and export it as a downloadable animated GIF or WebP data URL.
@@ -685,4 +789,4 @@ interface WebGLRenderer {
685
789
  */
686
790
  declare function tryCreateWebGLRenderer(canvas: HTMLCanvasElement): WebGLRenderer | null;
687
791
 
688
- export { ART_STYLE_PRESETS, type AnimationStyle, type ArtStyle, type AsciiBackgroundOptions, type AsciiCell, type AsciiFrame, type AsciiOptions, type AsciiResult, type AsciifySimpleOptions, type AuroraBackgroundOptions, CHARSETS, type CharsetKey, type CircuitBackgroundOptions, type ColorMode, DEFAULT_OPTIONS, type DnaBackgroundOptions, type FireBackgroundOptions, type GridBackgroundOptions, HOVER_PRESETS, type HoverEffect, type HoverPreset, type MorphBackgroundOptions, type MountWaveOptions, type NoiseBackgroundOptions, PALETTE_THEMES, type PaletteTheme, type PulseBackgroundOptions, type RainBackgroundOptions, type Recorder, type RecorderOptions, type RenderMode, type SilkBackgroundOptions, type SourceType, type StarsBackgroundOptions, type TerrainBackgroundOptions, type VoidBackgroundOptions, type WaveBackgroundOptions, type WebGLRenderer, asciiBackground, asciiText, asciiTextAnsi, asciify, asciifyGif, asciifyVideo, createRecorder, generateAnimatedEmbedCode, generateEmbedCode, gifToAsciiFrames, imageToAsciiFrame, mountWaveBackground, recordAndDownload, renderAuroraBackground, renderCircuitBackground, renderDnaBackground, renderFireBackground, renderFrameToCanvas, renderGridBackground, renderMorphBackground, renderNoiseBackground, renderPulseBackground, renderRainBackground, renderSilkBackground, renderStarsBackground, renderTerrainBackground, renderVoidBackground, renderWaveBackground, tryCreateWebGLRenderer, videoToAsciiFrames };
792
+ export { ART_STYLE_PRESETS, type AnimationStyle, type ArtStyle, type AsciiBackgroundOptions, type AsciiCell, type AsciiFrame, type AsciiOptions, type AsciiResult, type AsciifySimpleOptions, type AuroraBackgroundOptions, CHARSETS, type CharsetKey, type CircuitBackgroundOptions, type ColorMode, DEFAULT_OPTIONS, type DnaBackgroundOptions, type FireBackgroundOptions, type GridBackgroundOptions, HOVER_PRESETS, type HoverEffect, type HoverPreset, type MorphBackgroundOptions, type MountWaveOptions, type NoiseBackgroundOptions, PALETTE_THEMES, type PaletteTheme, type PulseBackgroundOptions, type RainBackgroundOptions, type Recorder, type RecorderOptions, type RenderMode, type SilkBackgroundOptions, type SourceType, type StarsBackgroundOptions, type TerrainBackgroundOptions, type TextBackgroundOptions, type VoidBackgroundOptions, type WaveBackgroundOptions, type WebGLRenderer, asciiBackground, asciiText, asciiTextAnsi, asciify, asciifyGif, asciifyVideo, buildTextFrame, createRecorder, gifToAsciiFrames, imageToAsciiFrame, mountWaveBackground, recordAndDownload, renderAuroraBackground, renderCircuitBackground, renderDnaBackground, renderFireBackground, renderFrameToCanvas, renderGridBackground, renderMorphBackground, renderNoiseBackground, renderPulseBackground, renderRainBackground, renderSilkBackground, renderStarsBackground, renderTerrainBackground, renderTextBackground, renderVoidBackground, renderWaveBackground, tryCreateWebGLRenderer, videoToAsciiFrames };
package/dist/index.d.ts CHANGED
@@ -121,20 +121,6 @@ declare function renderFrameToCanvas(ctx: CanvasRenderingContext2D, frame: Ascii
121
121
  intensity?: number;
122
122
  } | null): void;
123
123
 
124
- /**
125
- * Embed code generation — serializes ASCII frames into self-contained
126
- * HTML snippets that replay via the CDN embed runtime.
127
- */
128
-
129
- /**
130
- * Generate a static single-frame embed snippet.
131
- */
132
- declare function generateEmbedCode(frame: AsciiFrame, options: AsciiOptions, width: number, height: number): string;
133
- /**
134
- * Generate an animated multi-frame embed snippet (GIF / video).
135
- */
136
- declare function generateAnimatedEmbedCode(frames: AsciiFrame[], options: AsciiOptions, fps: number, width: number, height: number): string;
137
-
138
124
  /**
139
125
  * Simple one-call asciify API.
140
126
  * Wraps imageToAsciiFrame + renderFrameToCanvas behind easy-to-use helpers.
@@ -606,6 +592,124 @@ declare function asciiText(source: HTMLImageElement | HTMLVideoElement | HTMLCan
606
592
  */
607
593
  declare function asciiTextAnsi(source: HTMLImageElement | HTMLVideoElement | HTMLCanvasElement, options?: Partial<AsciiOptions>, targetWidth?: number, targetHeight?: number): string;
608
594
 
595
+ /**
596
+ * text-frame.ts — Build and render ASCII frames from tiling text patterns.
597
+ *
598
+ * Enables interactive text backgrounds with the full hover-effect system
599
+ * (spotlight, magnify, repel, glow, colorShift, …) without needing an image
600
+ * source.
601
+ *
602
+ * @example — basic usage
603
+ * ```ts
604
+ * import { renderTextBackground } from 'asciify-engine';
605
+ *
606
+ * function tick(ctx, w, h, mousePos) {
607
+ * renderTextBackground(ctx, w, h, 'asciify·engine·v1·', {
608
+ * hoverEffect: 'spotlight',
609
+ * hoverColor: '#d4ff00',
610
+ * }, mousePos);
611
+ * requestAnimationFrame(() => tick(ctx, w, h, mousePos));
612
+ * }
613
+ * ```
614
+ *
615
+ * @example — build the frame yourself and pass it to renderFrameToCanvas
616
+ * ```ts
617
+ * import { buildTextFrame, renderFrameToCanvas, DEFAULT_OPTIONS } from 'asciify-engine';
618
+ *
619
+ * const frame = buildTextFrame('hello world · ', 80, 24);
620
+ * renderFrameToCanvas(ctx, frame, {
621
+ * ...DEFAULT_OPTIONS,
622
+ * hoverEffect: 'repel',
623
+ * hoverStrength: 0.9,
624
+ * hoverColor: '#a0e8ff',
625
+ * }, width, height, 0, mousePos);
626
+ * ```
627
+ */
628
+
629
+ interface TextBackgroundOptions {
630
+ /**
631
+ * Character size in pixels.
632
+ * Controls the grid density: smaller → more cells, finer text.
633
+ * @default 10
634
+ */
635
+ fontSize?: number;
636
+ /**
637
+ * Line-height multiplier applied on top of `fontSize` to derive row height.
638
+ * Matches the default monospace aspect ratio used by the renderer.
639
+ * @default 1.6
640
+ */
641
+ lineHeight?: number;
642
+ /**
643
+ * Base colour for the text cells (inactive state).
644
+ * Accepts any CSS hex or rgb string.
645
+ * @default '#505050'
646
+ */
647
+ color?: string;
648
+ /**
649
+ * Base alpha for the text cells, 0–255.
650
+ * @default 100
651
+ */
652
+ opacity?: number;
653
+ /**
654
+ * Which hover effect to activate when `hoverPos` is supplied.
655
+ * @default 'spotlight'
656
+ */
657
+ hoverEffect?: HoverEffect;
658
+ /**
659
+ * Intensity of the hover distortion / glow, 0–1.
660
+ * @default 0.85
661
+ */
662
+ hoverStrength?: number;
663
+ /**
664
+ * Normalised radius of the hover influence zone, 0–1.
665
+ * @default 0.18
666
+ */
667
+ hoverRadius?: number;
668
+ /**
669
+ * Accent colour applied by the hover effect.
670
+ * @default '#d4ff00'
671
+ */
672
+ hoverColor?: string;
673
+ }
674
+ /**
675
+ * Build an `AsciiFrame` filled with a tiling text pattern.
676
+ *
677
+ * The `text` string is repeated (wrapping at column boundaries) across every
678
+ * cell of the `cols × rows` grid. Each cell carries the supplied base colour
679
+ * and opacity as `{r, g, b, a}` values.
680
+ *
681
+ * The returned frame can be passed directly to `renderFrameToCanvas` with any
682
+ * `AsciiOptions` including hover effects.
683
+ *
684
+ * @param text - Pattern string to tile across the grid (e.g. `'hello · '`)
685
+ * @param cols - Number of character columns
686
+ * @param rows - Number of character rows
687
+ * @param color - Base RGB colour string for the cells (default: `'#505050'`)
688
+ * @param opacity - Base alpha 0–255 (default: `100`)
689
+ */
690
+ declare function buildTextFrame(text: string, cols: number, rows: number, color?: string, opacity?: number): AsciiFrame;
691
+ /**
692
+ * All-in-one: build a tiling text grid and render it to a canvas with the
693
+ * full hover-effect system (spotlight, magnify, repel, glow, colorShift, …).
694
+ *
695
+ * Call this inside a `requestAnimationFrame` loop, passing updated `hoverPos`
696
+ * each frame to get smooth interactive effects.
697
+ *
698
+ * @param ctx - 2D rendering context of the target canvas
699
+ * @param width - Canvas logical width in pixels
700
+ * @param height - Canvas logical height in pixels
701
+ * @param text - Pattern string to tile (e.g. `'asciify·engine·v1·'`)
702
+ * @param options - {@link TextBackgroundOptions}
703
+ * @param hoverPos - Normalised mouse position `{x, y}` in 0–1 range,
704
+ * optionally with an `intensity` multiplier (0–1).
705
+ * Pass `null` or omit to render without hover.
706
+ */
707
+ declare function renderTextBackground(ctx: CanvasRenderingContext2D, width: number, height: number, text: string, options?: TextBackgroundOptions, hoverPos?: {
708
+ x: number;
709
+ y: number;
710
+ intensity?: number;
711
+ } | null): void;
712
+
609
713
  /**
610
714
  * record() — capture a rolling frame buffer from a running ASCII canvas
611
715
  * and export it as a downloadable animated GIF or WebP data URL.
@@ -685,4 +789,4 @@ interface WebGLRenderer {
685
789
  */
686
790
  declare function tryCreateWebGLRenderer(canvas: HTMLCanvasElement): WebGLRenderer | null;
687
791
 
688
- export { ART_STYLE_PRESETS, type AnimationStyle, type ArtStyle, type AsciiBackgroundOptions, type AsciiCell, type AsciiFrame, type AsciiOptions, type AsciiResult, type AsciifySimpleOptions, type AuroraBackgroundOptions, CHARSETS, type CharsetKey, type CircuitBackgroundOptions, type ColorMode, DEFAULT_OPTIONS, type DnaBackgroundOptions, type FireBackgroundOptions, type GridBackgroundOptions, HOVER_PRESETS, type HoverEffect, type HoverPreset, type MorphBackgroundOptions, type MountWaveOptions, type NoiseBackgroundOptions, PALETTE_THEMES, type PaletteTheme, type PulseBackgroundOptions, type RainBackgroundOptions, type Recorder, type RecorderOptions, type RenderMode, type SilkBackgroundOptions, type SourceType, type StarsBackgroundOptions, type TerrainBackgroundOptions, type VoidBackgroundOptions, type WaveBackgroundOptions, type WebGLRenderer, asciiBackground, asciiText, asciiTextAnsi, asciify, asciifyGif, asciifyVideo, createRecorder, generateAnimatedEmbedCode, generateEmbedCode, gifToAsciiFrames, imageToAsciiFrame, mountWaveBackground, recordAndDownload, renderAuroraBackground, renderCircuitBackground, renderDnaBackground, renderFireBackground, renderFrameToCanvas, renderGridBackground, renderMorphBackground, renderNoiseBackground, renderPulseBackground, renderRainBackground, renderSilkBackground, renderStarsBackground, renderTerrainBackground, renderVoidBackground, renderWaveBackground, tryCreateWebGLRenderer, videoToAsciiFrames };
792
+ export { ART_STYLE_PRESETS, type AnimationStyle, type ArtStyle, type AsciiBackgroundOptions, type AsciiCell, type AsciiFrame, type AsciiOptions, type AsciiResult, type AsciifySimpleOptions, type AuroraBackgroundOptions, CHARSETS, type CharsetKey, type CircuitBackgroundOptions, type ColorMode, DEFAULT_OPTIONS, type DnaBackgroundOptions, type FireBackgroundOptions, type GridBackgroundOptions, HOVER_PRESETS, type HoverEffect, type HoverPreset, type MorphBackgroundOptions, type MountWaveOptions, type NoiseBackgroundOptions, PALETTE_THEMES, type PaletteTheme, type PulseBackgroundOptions, type RainBackgroundOptions, type Recorder, type RecorderOptions, type RenderMode, type SilkBackgroundOptions, type SourceType, type StarsBackgroundOptions, type TerrainBackgroundOptions, type TextBackgroundOptions, type VoidBackgroundOptions, type WaveBackgroundOptions, type WebGLRenderer, asciiBackground, asciiText, asciiTextAnsi, asciify, asciifyGif, asciifyVideo, buildTextFrame, createRecorder, gifToAsciiFrames, imageToAsciiFrame, mountWaveBackground, recordAndDownload, renderAuroraBackground, renderCircuitBackground, renderDnaBackground, renderFireBackground, renderFrameToCanvas, renderGridBackground, renderMorphBackground, renderNoiseBackground, renderPulseBackground, renderRainBackground, renderSilkBackground, renderStarsBackground, renderTerrainBackground, renderTextBackground, renderVoidBackground, renderWaveBackground, tryCreateWebGLRenderer, videoToAsciiFrames };
package/dist/index.js CHANGED
@@ -960,84 +960,6 @@ function renderFrameToCanvas(ctx, frame, options, canvasWidth, canvasHeight, tim
960
960
  ctx.globalAlpha = 1;
961
961
  }
962
962
 
963
- // src/core/embed-gen.ts
964
- var EMBED_CDN_VERSION = "1.0.17";
965
- function serializeFrame(frame, fullColor) {
966
- const rows = frame.length;
967
- const cols = rows > 0 ? frame[0].length : 0;
968
- const stride = fullColor ? 3 : 1;
969
- const buf = new Uint8Array(1 + rows * cols * stride);
970
- buf[0] = stride;
971
- let i = 1;
972
- for (let y = 0; y < rows; y++) {
973
- for (let x = 0; x < cols; x++) {
974
- const cell = frame[y][x];
975
- if (fullColor) {
976
- buf[i++] = cell.r;
977
- buf[i++] = cell.g;
978
- buf[i++] = cell.b;
979
- } else {
980
- buf[i++] = Math.round(0.299 * cell.r + 0.587 * cell.g + 0.114 * cell.b);
981
- }
982
- }
983
- }
984
- let binary = "";
985
- for (let j = 0; j < buf.length; j++) binary += String.fromCharCode(buf[j]);
986
- return btoa(binary);
987
- }
988
- function buildEmbedOpts(options, rows, cols, width, height, fps, animated) {
989
- const o = {
990
- r: rows,
991
- c: cols,
992
- w: width,
993
- h: height,
994
- cs: options.charset,
995
- cm: options.colorMode,
996
- as: options.animationStyle,
997
- sp: options.animationSpeed,
998
- inv: options.invert,
999
- hs: options.hoverStrength,
1000
- hr: options.hoverRadius,
1001
- he: options.hoverEffect,
1002
- hc: options.hoverColor,
1003
- dr: options.dotSizeRatio,
1004
- dots: options.renderMode === "dots"
1005
- };
1006
- if (options.colorMode === "accent") o.ac = options.accentColor;
1007
- if (fps !== void 0) o.fps = fps;
1008
- if (animated) o.anim = true;
1009
- return JSON.stringify(o);
1010
- }
1011
- var CDN_SCRIPT = `<script src="https://cdn.jsdelivr.net/npm/asciify-engine@${EMBED_CDN_VERSION}/dist/embed.js" async></script>`;
1012
- function generateEmbedCode(frame, options, width, height) {
1013
- const rows = frame.length;
1014
- if (rows === 0) return "";
1015
- const cols = frame[0].length;
1016
- const isFullColor = options.colorMode === "fullcolor";
1017
- const data = serializeFrame(frame, isFullColor);
1018
- const id = `ar-${Math.random().toString(36).slice(2, 9)}`;
1019
- const opts = buildEmbedOpts(options, rows, cols, width, height);
1020
- return `<!-- Asciify Embed -->
1021
- <canvas id="${id}" data-asciify-opts='${opts}' width="${width}" height="${height}"></canvas>
1022
- <script type="application/json" id="${id}-d">"${data}"</script>
1023
- ${CDN_SCRIPT}
1024
- <!-- /Asciify Embed -->`;
1025
- }
1026
- function generateAnimatedEmbedCode(frames, options, fps, width, height) {
1027
- if (frames.length === 0) return "";
1028
- const rows = frames[0].length;
1029
- const cols = frames[0][0].length;
1030
- const isFullColor = options.colorMode === "fullcolor";
1031
- const allData = frames.map((f) => serializeFrame(f, isFullColor));
1032
- const id = `ar-${Math.random().toString(36).slice(2, 9)}`;
1033
- const opts = buildEmbedOpts(options, rows, cols, width, height, fps, true);
1034
- return `<!-- Asciify Animated Embed -->
1035
- <canvas id="${id}" data-asciify-opts='${opts}' width="${width}" height="${height}"></canvas>
1036
- <script type="application/json" id="${id}-d">${JSON.stringify(allData)}</script>
1037
- ${CDN_SCRIPT}
1038
- <!-- /Asciify Animated Embed -->`;
1039
- }
1040
-
1041
963
  // src/core/simple-api.ts
1042
964
  async function asciify(source, canvas, { fontSize = 10, style = "classic", options = {} } = {}) {
1043
965
  let el;
@@ -2312,6 +2234,47 @@ function asciiTextAnsi(source, options = {}, targetWidth, targetHeight) {
2312
2234
  return lines.join("\n");
2313
2235
  }
2314
2236
 
2237
+ // src/core/text-frame.ts
2238
+ function buildTextFrame(text, cols, rows, color = "#505050", opacity = 100) {
2239
+ if (!text || cols <= 0 || rows <= 0) return [];
2240
+ const parsed = parseColor(color) ?? { r: 80, g: 80, b: 80 };
2241
+ const pattern = text;
2242
+ const len = pattern.length;
2243
+ return Array.from(
2244
+ { length: rows },
2245
+ (_, row) => Array.from({ length: cols }, (_2, col) => ({
2246
+ char: pattern[(row * cols + col) % len],
2247
+ r: parsed.r,
2248
+ g: parsed.g,
2249
+ b: parsed.b,
2250
+ a: opacity
2251
+ }))
2252
+ );
2253
+ }
2254
+ function renderTextBackground(ctx, width, height, text, options = {}, hoverPos) {
2255
+ const {
2256
+ fontSize = 10,
2257
+ lineHeight = 1.6,
2258
+ color = "#505050",
2259
+ opacity = 100,
2260
+ hoverEffect = "spotlight",
2261
+ hoverStrength = 0.85,
2262
+ hoverRadius = 0.18,
2263
+ hoverColor = "#d4ff00"
2264
+ } = options;
2265
+ const cols = Math.max(1, Math.floor(width / fontSize));
2266
+ const rows = Math.max(1, Math.floor(height / (fontSize * lineHeight)));
2267
+ const frame = buildTextFrame(text, cols, rows, color, opacity);
2268
+ const renderOpts = {
2269
+ ...DEFAULT_OPTIONS,
2270
+ hoverEffect,
2271
+ hoverStrength,
2272
+ hoverRadius,
2273
+ hoverColor
2274
+ };
2275
+ renderFrameToCanvas(ctx, frame, renderOpts, width, height, 0, hoverPos ?? null);
2276
+ }
2277
+
2315
2278
  // src/core/record.ts
2316
2279
  function createRecorder(canvas, options = {}) {
2317
2280
  const {
@@ -2901,6 +2864,6 @@ function tryCreateWebGLRenderer(canvas) {
2901
2864
  }
2902
2865
  }
2903
2866
 
2904
- export { ART_STYLE_PRESETS, CHARSETS, DEFAULT_OPTIONS, HOVER_PRESETS, PALETTE_THEMES, asciiBackground, asciiText, asciiTextAnsi, asciify, asciifyGif, asciifyVideo, createRecorder, generateAnimatedEmbedCode, generateEmbedCode, gifToAsciiFrames, imageToAsciiFrame, mountWaveBackground, recordAndDownload, renderAuroraBackground, renderCircuitBackground, renderDnaBackground, renderFireBackground, renderFrameToCanvas, renderGridBackground, renderMorphBackground, renderNoiseBackground, renderPulseBackground, renderRainBackground, renderSilkBackground, renderStarsBackground, renderTerrainBackground, renderVoidBackground, renderWaveBackground, tryCreateWebGLRenderer, videoToAsciiFrames };
2867
+ export { ART_STYLE_PRESETS, CHARSETS, DEFAULT_OPTIONS, HOVER_PRESETS, PALETTE_THEMES, asciiBackground, asciiText, asciiTextAnsi, asciify, asciifyGif, asciifyVideo, buildTextFrame, createRecorder, gifToAsciiFrames, imageToAsciiFrame, mountWaveBackground, recordAndDownload, renderAuroraBackground, renderCircuitBackground, renderDnaBackground, renderFireBackground, renderFrameToCanvas, renderGridBackground, renderMorphBackground, renderNoiseBackground, renderPulseBackground, renderRainBackground, renderSilkBackground, renderStarsBackground, renderTerrainBackground, renderTextBackground, renderVoidBackground, renderWaveBackground, tryCreateWebGLRenderer, videoToAsciiFrames };
2905
2868
  //# sourceMappingURL=index.js.map
2906
2869
  //# sourceMappingURL=index.js.map