-
Notifications
You must be signed in to change notification settings - Fork 14
Expand file tree
/
Copy pathsketch.js
More file actions
152 lines (136 loc) · 6.4 KB
/
Copy pathsketch.js
File metadata and controls
152 lines (136 loc) · 6.4 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
// p5.js port of the single-line font from Abel Vincze's Gear Generator (geargenerator.com).
// Ported from https://www.robopenguins.com/assets/wp-content/pages/geargenerator/index.html
// Note that Vincze has a more advanced version at https://geargenerator.com/beta/.
// Ported to p5.js by Golan Levin, 2026
//
// Font data format (three parallel arrays):
// font[0] — charset string: each character is the key for the corresponding glyph
// font[1] — coordinate lookup table: pairs of ASCII digit characters encoding
// (x, y) points on a 7×9 integer grid (x: 0–6, y: 0–8)
// font[2] — space-separated glyph entries; within each entry:
// • first character: the advance width as a single digit (0–6)
// • uppercase/lowercase ASCII letters: index into font[1] via getindex()
// • '/' and other non-letter chars: stroke break (pen-up / moveTo)
//
// Coordinate system: x=0 is left edge of glyph; y=0 is baseline, y=8 is cap height.
// In p5.js: screen_x = gx + x*sca, screen_y = gy − y*sca.
// ─── p5.js sketch ───────────────────────────────────────────────────────────
function setup() {
createCanvas(800, 300);
pixelDensity(2);
noLoop();
}
function draw() {
background(0);
stroke(255);
strokeWeight(1.2);
strokeCap(ROUND);
strokeJoin(ROUND);
noFill();
let tx = 40;
let sca = 5.25; // scale: font units to pixels
let sp = 1; // inter-character spacing in font units
drawString("ABCDEFGHIJKLMNOPQRSTUVWXYZ", tx, 80, sca, sp);
drawString("abcdefghijklmnopqrstuvwxyz", tx, 140, sca, sp);
drawString("0123456789 +-/=*;:,.<>", tx, 200, sca, sp);
drawString("Hello, World", tx, 260, sca, sp);
}
function keyPressed() {
if (key === 's') save('vincze_geargenerator_font.png');
}
// ========================================================
// GEARGENERATOR FONT
// ─── Font data (from geargenerator.js, line 37)
// Correction: Q entry changed from "4DVMPQLKJD" → "4DVMPQLKJD/YE"
// The original Q had no tail stroke, rendering identically to O.
// Added tail: Y=(3,3) → E=(4,2), a short diagonal from inside the lower-right
// of the loop to the bottom-right corner (y=2, the floor of uppercase letters).
const font = [
"ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+-/=*;:,.<>",
"0204284442324335464738181215080307480525452224683316263634174130100106373120004014232713",
"4ABCDE/BD 4AFGDHIJKLM/NH/OL 4GFMPQLKJ 4AFGJKO/LM 4EAOR/ST 4AOR/ST 4HUEMPQLR 4ER/US/OA 2VA/ML/CO 4RGFMP 4ENR/AO/NS 4EAO 4ERWOA 4REOA 4UGFMPQLKJU 4SHIJKOA 4DVMPQLKJD/YE 4ENHIJKOA/NS 4JKLQGFMP 4RO/CV 4RGFMPO 6XFO 6XEHVO 4RA/EO 4RTO/TV 4EARO 4YVMPSZaHYE 4OBabUGFVBA 4EMPSZI 4EDVMPSZaDR 4FMPSZbUcB 4MdCKJ/HS 4EMPSZbUefgh 4BabUE/AO 0Ai/QO 3Kj/bklgh 4EWI/AO/WB 1MPO 4Ai/SZTbUE/WT 4Ai/BabUE 4GFMPSZbUG 4mi/SZbUGFA 4nI/EMPSZbU 4Ai/BabU 4IZSocGFA 4GFpC/Ii 4IE/DVMPi 4IVi 4IFaMi 4IA/Ei 4Igm/Vi 4EAIi 3YVMPQLCjY 2QLM/VA 4EABNHIJKLQ 4QLKJIHDGFMP/TH 4DBKF 4ROibUGFMP 4SHDGFMPiCK 4ORV 4NBPMFGDHNiQLKJIH 4UNiQLKJDVM 4pq/US 4US 4RA 4Ii/DB 4US/pq/JP/GQ 1ZN/oMh 1ZN/or 1rMh 0PA 3KSF 3OHA"
];
// Map an ASCII character code to a byte-offset into font[1].
// Letters A–Z map to offsets 0, 2, 4 … 50.
// Letters a–z map to offsets 52, 54 … 102.
// Digits, punctuation, and '/' yield a negative value → stroke break.
function getindex(code) {
code -= 65;
if (code > 25) code -= 6; // skip the 6 ASCII chars between 'Z' and 'a'
return code * 2;
}
// Parse the glyph data for a single character.
// Returns an array where:
// data[0] = advance width in font units (-1 if character unknown)
// data[1..n] = stroke arrays; each stroke is an array of {x, y} objects
//
// Each letter in font[2]'s glyph entry is decoded by getindex() to a position
// in font[1], from which a two-digit (x, y) coordinate is read.
// Non-letter chars (digits, '/') create a new stroke (pen-up).
function getchardata(chr) {
const i = font[0].lastIndexOf(chr);
const data = [];
if (i > -1) {
const chdata = font[2].split(" ")[i];
let l = 0;
data[0] = Number(chdata.charAt(0)); // advance width
for (let p = 0; p < chdata.length; p++) {
const pi = getindex(chdata.charCodeAt(p));
if (pi < 0) {
// Non-letter character → begin a new stroke
data[++l] = [];
} else {
// Letter character → look up (x, y) from the coordinate table
if (!data[l]) data[l] = [];
const pair = font[1].substr(pi, 2);
data[l].push({ x: Number(pair[0]), y: Number(pair[1]) });
}
}
} else {
data[0] = (chr === " ") ? 3 : -1; // space advances 3 units; unknown = -1
}
return data;
}
// ─── Rendering ───────────────────────────────────────────────────────────────
// Draw a single glyph.
// ch: the character to render
// gx, gy: pixel position — gx is the left edge, gy is the baseline (font y=0)
// sca: scale factor (font units → pixels)
function drawGlyph(ch, gx, gy, sca) {
const data = getchardata(ch);
if (data[0] < 0) return; // unknown character; skip
for (let l = 1; l < data.length; l++) {
const stroke = data[l];
if (!stroke || stroke.length === 0) continue;
beginShape();
for (const pt of stroke) {
vertex(gx + pt.x * sca, // x increases rightward
gy - pt.y * sca); // y=0 at baseline, y=8 at cap top
}
endShape();
}
}
// Font metric: cap-height in font units (y=0 at baseline, y=8 at top of capitals)
const GG_CAPH = 8;
// Draw a string of text.
// str: text to render
// x, y: pixel position — x is left edge, y is the baseline
// sca: scale factor (font units → pixels)
// spacing: extra gap between characters in font units (default 1)
// lineH: line-height multiplier for '\n' newlines (default 1.6)
function drawString(str, x, y, sca, spacing = 1, lineH = 1.6) {
let cx = x;
let cy = y;
for (let i = 0; i < str.length; i++) {
const ch = str[i];
if (ch === "\n") {
cy += GG_CAPH * sca * lineH;
cx = x;
continue;
}
drawGlyph(ch, cx, cy, sca);
const data = getchardata(ch);
const adv = (data[0] >= 0) ? data[0] : 3; // unknown chars advance like a space
cx += (adv + spacing) * sca;
}
}