an invented character in five brush strokes, sealed in red
painted by DeepSeek V4p5 2.3.2 · brush 2.2.2 · 2026-08-24
// composition: an invented five-stroke character sitting upper-left of center on bare paper; red seal square anchors lower-right
// layering: each stroke built from layered tapering marker passes (heavy entry, thin exit), charcoal for the plunge, spray flecks at stroke ends, seal last
const PALETTE = [
"#f0ead9", // bare warm paper
"#1c1a18", // ink black
"#3a3632", // dry ink, second passes
"#b8352b", // seal red
];
// draw one calligraphic stroke: full path thin, then shortened heavier passes
// stacked toward the entry, so weight tapers along the gesture
function stroke5(pts, wBase, brushName, reversed) {
const path = reversed ? pts.slice().reverse() : pts;
const fractions = [1.0, 0.68, 0.4];
const weights = [wBase * 0.55, wBase * 0.85, wBase * 1.25];
for (let p = 0; p < 3; p++) {
const keep = Math.max(2, Math.ceil(path.length * fractions[p]));
brush.set(brushName, p === 0 ? "#3a3632" : "#1c1a18", weights[p]);
brush.beginShape(0.5);
for (let i = 0; i < keep; i++) {
brush.vertex(
path[i][0] + randomGaussian(0, 1.4),
path[i][1] + randomGaussian(0, 1.4)
);
}
brush.endShape(false);
}
// spray flecks where the brush left the paper
const end = path[path.length - 1];
brush.set("spray", "#1c1a18", random(2, 3));
for (let i = 0; i < 3; i++) {
const a = random(0, Math.PI * 2);
const d = random(2, 14);
brush.line(end[0], end[1], end[0] + Math.cos(a) * d, end[1] + Math.sin(a) * d);
}
}
function setup() {
createCanvas(800, 800, WEBGL);
brush.scaleBrushes(2.6);
noLoop();
}
function draw() {
translate(-width / 2, -height / 2);
background("#f0ead9");
// the character: five strokes, upper-left of center, no script's glyph
// 1 — broad horizontal sweep, heavy at the left entry
stroke5(
[[176, 232], [268, 218], [366, 226], [438, 248]],
7.5, "marker", false
);
// 2 — the plunge: charcoal, dropping through the sweep, heavy at the top
stroke5(
[[298, 168], [306, 280], [296, 388], [270, 470]],
9, "charcoal", false
);
// 3 — rising diagonal flick, entry low-left, thrown off to the right
stroke5(
[[212, 402], [292, 356], [378, 330], [452, 334]],
6, "marker", false
);
// 4 — curved hook closing under the plunge, heavy where it turns in
stroke5(
[[416, 392], [452, 442], [436, 500], [366, 520], [316, 502]],
6.5, "marker", true
);
// 5 — short falling accent, alone at the upper right of the character
stroke5(
[[452, 168], [478, 208], [488, 252]],
5.5, "marker", false
);
// the seal: red square lower-right, edges rough, two pooling passes
brush.noStroke();
brush.fillBleed(0.4, "out");
brush.fillTexture(0.7, 0.8);
brush.fill("#b8352b", 185);
brush.beginShape(0.2);
brush.vertex(560 + randomGaussian(0, 2), 570 + randomGaussian(0, 2));
brush.vertex(646 + randomGaussian(0, 2), 566 + randomGaussian(0, 2));
brush.vertex(650 + randomGaussian(0, 2), 652 + randomGaussian(0, 2));
brush.vertex(564 + randomGaussian(0, 2), 656 + randomGaussian(0, 2));
brush.endShape(true);
brush.fill("#b8352b", 110);
brush.beginShape(0.2);
brush.vertex(566, 576);
brush.vertex(642, 572);
brush.vertex(644, 646);
brush.vertex(570, 650);
brush.endShape(true);
// paper cut-marks inside the seal — abstract, not letterforms
brush.set("marker", "#f0ead9", 3);
brush.line(584, 588, 584, 634);
brush.line(604, 586, 630, 586);
brush.line(612, 604, 612, 640);
brush.line(628, 612, 630, 640);
}