Skip to content

Commit f89492e

Browse files
committed
Add text input
1 parent b10223b commit f89492e

1 file changed

Lines changed: 64 additions & 0 deletions

File tree

ishihara/ishihara.js

Lines changed: 64 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -33,6 +33,7 @@ const ishihara_input = {
3333
load_image() {
3434
document.getElementById('image_upload').click();
3535
},
36+
text: '',
3637
circular: true,
3738
resize: true,
3839
edge_detection: true,
@@ -67,6 +68,7 @@ const ishihara_input = {
6768

6869
generating = true;
6970

71+
if (ishihara_input.text) renderText();
7072
const img_data = img_ctx.getImageData(0, 0, canvas.width, canvas.height);
7173
ctx.fillStyle = ishihara_input.background_color;
7274
ctx.fillRect(0, 0, canvas.width, canvas.height);
@@ -133,6 +135,67 @@ const ishihara_input = {
133135
}
134136
};
135137

138+
function renderText() {
139+
img_ctx.fillStyle = 'white';
140+
img_ctx.fillRect(0, 0, img_canvas.width, img_canvas.height);
141+
ctx.fillStyle = 'white';
142+
ctx.fillRect(0, 0, canvas.width, canvas.height);
143+
144+
const text = ishihara_input.text;
145+
if (!text) return;
146+
147+
const cw = img_canvas.width;
148+
const ch = img_canvas.height;
149+
const maxLineWidth = ishihara_input.circular
150+
? Math.min(cw, ch) * 0.75
151+
: cw * 0.95;
152+
153+
const wrapText = (fontSize) => {
154+
img_ctx.font = `bold ${fontSize}px sans-serif`;
155+
const lines = [];
156+
for (const paragraph of text.split('\n')) {
157+
let currentLine = '';
158+
for (const word of paragraph.split(' ')) {
159+
const testLine = currentLine ? `${currentLine} ${word}` : word;
160+
if (currentLine && img_ctx.measureText(testLine).width > maxLineWidth) {
161+
lines.push(currentLine);
162+
currentLine = word;
163+
} else {
164+
currentLine = testLine;
165+
}
166+
}
167+
lines.push(currentLine);
168+
}
169+
return lines;
170+
};
171+
172+
let lo = 1, hi = 4000;
173+
while (hi - lo > 1) {
174+
const mid = (lo + hi) >> 1;
175+
const lines = wrapText(mid);
176+
const totalHeight = lines.length * mid * 1.2;
177+
const maxW = Math.max(...lines.map(l => img_ctx.measureText(l).width));
178+
const fits = ishihara_input.circular
179+
? Math.hypot(maxW, totalHeight) <= Math.min(cw, ch) * 0.9
180+
: maxW <= cw * 0.95 && totalHeight <= ch * 0.9;
181+
if (fits) lo = mid; else hi = mid;
182+
}
183+
184+
const lines = wrapText(lo);
185+
const lineHeight = lo * 1.2;
186+
const firstLineY = ch / 2 - (lines.length - 1) * lineHeight / 2;
187+
188+
img_ctx.font = `bold ${lo}px sans-serif`;
189+
img_ctx.fillStyle = 'black';
190+
img_ctx.textAlign = 'center';
191+
img_ctx.textBaseline = 'middle';
192+
for (let i = 0; i < lines.length; i++) {
193+
img_ctx.fillText(lines[i], cw / 2, firstLineY + i * lineHeight);
194+
}
195+
196+
ctx.drawImage(img_canvas, 0, 0, canvas.width, canvas.height);
197+
}
198+
136199
function set_colors_folders() {
137200
for (let i = 0; i < 6; i++) {
138201
hide_gui_element(colors_on_folder, 'color_on' + i, i >= ishihara_input.n_colors_on);
@@ -226,6 +289,7 @@ const gui = new dat.GUI({
226289
gui.remember(ishihara_input);
227290

228291
gui.add(ishihara_input, 'load_image').name('Load image');
292+
gui.add(ishihara_input, 'text').name('Text').onChange(() => renderText());
229293
gui.add(ishihara_input, 'circular').name('Circular');
230294
gui.add(ishihara_input, 'resize').name('Resize');
231295
gui.add(ishihara_input, 'edge_detection').name('Edge detection');

0 commit comments

Comments
 (0)