@thi.ng/text-canvas
Version:
Text based canvas, drawing, plotting, tables with arbitrary formatting (incl. ANSI/HTML)
88 lines (87 loc) • 2.18 kB
JavaScript
import { peek } from "@thi.ng/arrays/peek";
import { clamp0 } from "@thi.ng/math/interval";
import { wordWrapLines } from "@thi.ng/strings/word-wrap";
import {
beginClip,
beginStyle,
endClip,
endStyle
} from "./canvas.js";
import { fillRect, strokeRect } from "./rect.js";
const textLine = (canvas, x, y, line, format = canvas.format) => {
x |= 0;
y |= 0;
const { x1, y1, x2, y2 } = peek(canvas.clipRects);
if (y < y1 || y >= y2 || x >= x2) return;
let i = 0;
if (x < x1) {
i = x1 - x;
x = x1;
}
const { data, width } = canvas;
const n = line.length;
format <<= 16;
for (let idx = x + y * width; i < n && x < x2; i++, x++, idx++) {
data[idx] = line.charCodeAt(i) | format;
}
};
const textLines = (canvas, x, y, lines, format = canvas.format) => {
for (let line of lines) {
textLine(canvas, x, y, line, format);
y++;
}
return y;
};
const textColumn = (canvas, x, y, width, txt, format = canvas.format, hard = false) => {
x |= 0;
y |= 0;
width |= 0;
const height = canvas.height;
for (let line of wordWrapLines(txt, { width, hard })) {
textLine(canvas, x, y, line.toString(), format);
y++;
if (y >= height) break;
}
return y;
};
const textBox = (canvas, x, y, width, height, txt, opts = {}) => {
const {
format = canvas.format,
hard = false,
padding: [padX, padY] = [0, 0],
style
} = opts;
const currFmt = canvas.format;
canvas.format = format;
style && beginStyle(canvas, style);
x |= 0;
y |= 0;
width |= 0;
let innerW = width - 2 - 2 * padX;
let innerH = 0;
const lines = wordWrapLines(txt, { width: innerW, hard }).map(
(l) => l.toString()
);
if (height < 0) {
innerH = lines.length + 2;
height = innerH + 2 * padY;
} else {
innerH = clamp0(height - 2);
}
strokeRect(canvas, x, y, width, height);
fillRect(canvas, x + 1, y + 1, width - 2, height - 2, " ");
x += 1 + padX;
y += 1 + padY;
beginClip(canvas, x, y, innerW, innerH);
y = textLines(canvas, x, y, lines);
endClip(canvas);
style && endStyle(canvas);
canvas.format = currFmt;
return y + height;
};
export {
textBox,
textColumn,
textLine,
textLines
};