Spell checker now IS included. Added corrections to the original by llemarie: Whitepaper
Log in to post a comment.
// Forked from "Whitepaper" by llemarie // https://turtletoy.net/turtle/89ece0eb84 // LL 2021 Canvas.setpenopacity(1); const tt = new ClippingTurtle(); const text_size = 2; // min=1 max=5 step=0.25 const columns = 3; // min=1 max=4 step=1 const seed=0; // min=0 max=100 step=1 var rng; const fake_text = new FakeText(); function walk(i) { if (i==0) { rng = new RNG(seed); const paper_width = 130; const paper_height = paper_width / 8.5 * 11; const margin = paper_width * 0.05 / columns; const title_size = text_size * 5; const subtitle_size = text_size * 2.5; const margin_top = margin * 2 + title_size + subtitle_size; // Draw pages tt.jump(-paper_width/2, -paper_height/2); drawPaper(tt, paper_width, paper_height, 5); // Draw title for (var t=0; t<3; t++) { const title_length = ((paper_width - margin * 2) / title_size / 1.5) | 0; const title_text = generateRandomText(1, title_length); const title_width = title_length * title_size; tt.jump(-title_width/2, -paper_height/2 + margin); fake_text.print(tt, title_text, title_size); } // Draw subtitle { const subtitle_length = ((paper_width - margin * 2) / subtitle_size / 2) | 0; const subtitle_text = generateRandomText(1, subtitle_length); const subtitle_width = subtitle_length * subtitle_size; tt.jump(-subtitle_width/2, -paper_height/2 + margin + title_size); fake_text.print(tt, subtitle_text, subtitle_size); } // Draw columns for (var c=0; c<columns; c++) { const left = -paper_width/2 + margin + c * (paper_width/columns - margin/columns); const top = -paper_height/2 + margin_top; const width = paper_width/columns - margin - margin / columns; const height = paper_height - margin - margin_top; drawColumn(tt, left, top, width, height, text_size); } // Draw corrections for(let j = -1; j < 2; j = j + 2) { const cmargin = 5; const width = (100 - paper_width / 2) - cmargin - cmargin; const lines = ((paper_height - margin - margin_top) / text_size) - 2; const line_width = (width / text_size) | 0; const top = -paper_height/2 + margin_top; for(let i = 0; i < lines; i = i + 2) { const line_count = random() * 3; if(random() > .75) { let col_text = generateRandomText(line_count, line_width); tt.jump(j == -1? -100 + cmargin: 100 - (cmargin / 2) - width, top + (i * text_size)); fake_text.print(tt, col_text, text_size); i = i + line_count; tt.seth(90); tt.up(); tt.forward(text_size / 2); tt.seth((j == -1? 0: 180)); tt.forward(j == -1? margin: width); tt.seth((j == -1? 0: 180) + ((random() * 20) - 10)); tt.down(); tt.forward((j == -1? margin: margin * 2) + random() * paper_width / 2); } } } } return false; } function drawColumn(turtle, x, y, w, h, text_size) { { const line_count = (w / text_size) | 0; const top_line = (random() * (h / text_size - line_count)) | 0; drawFigure(turtle, x, y + top_line * text_size, w, line_count * text_size); turtle.setWindow(x, y + top_line * text_size, x + w * 1.01, y + (top_line + line_count) * text_size); turtle.drawInsideWindow = false; } { const line_count = (h / text_size) | 0; const line_width = (w / text_size) | 0; const col_text = generateRandomText(line_count, line_width); turtle.jump(x, y); fake_text.print(turtle, col_text, text_size); } turtle.setWindow([]); } var available_figures = []; function drawFigure(turtle, x, y, w, h) { const figure_count = 5; if (available_figures.length == 0) available_figures = [drawDNA, drawLissajous, drawChart, drawFlower, drawMoire, drawDefault]; turtle.setWindow(x + w * 0.05, y + h * 0.05, x + w * 0.95, y + h * 0.95); turtle.drawInsideWindow = true; const figure_index = (random() * available_figures.length) | 0; available_figures[figure_index](turtle, x, y, w, h); available_figures.splice(figure_index, 1); } function drawDefault(turtle, x, y, w, h) { const cx = x + w/2; const cy = y + h/2; const r = 0.45 * Math.min(w, h); const step = Math.PI * 2 / (10 + random() * 10); const add = step + 10 * random(); for (var a = 0; a < Math.PI * 2; a += step) { turtle.jump(cx + r * Math.cos(a), cy + r * Math.sin(a)); turtle.goto(cx + r * Math.cos(a+add), cy + r * Math.sin(a+add)); } } function drawMoire(turtle, x, y, w, h) { for (var t=0; t<=1; t++) { const cx = x + w * random(); const cy = y + h * random(); const interval = 1.5; turtle.down(); for (var r = interval; r < Math.max(w, h) * 2; r += interval) { turtle.jump(cx, cy - r); turtle.circle(r); } } } function drawLissajous(turtle, x, y, w, h) { const cx = x + w/2; const cy = y + h/2; const r = 0.45 * Math.min(w, h); const step = Math.PI * 2 / ((10 + random() * 10)|0); const mul = random() * 30.1 + 1; turtle.jump(cx + r, cy); for (var a = 0; a < Math.PI * 2 * 10; a += step) { turtle.goto(cx + r * Math.cos(a), cy + r * Math.sin(a*mul)); } } function drawFlower(turtle, x, y, w, h) { const cx = x + w/2; const cy = y + h/2; const r = 0.25 * Math.min(w, h); const r2 = r * 0.8; const step = Math.PI * 2 / 100; const mul = random() * 10 + 1; turtle.up(); for (var a = 0; a < Math.PI * 2 * 2.1; a += step) { turtle.goto(cx + r * Math.cos(a) + r2 * Math.cos(a * mul), cy + r * Math.sin(a) + r2 * Math.sin(a * mul)); turtle.down(); } } function rotX(x, y, a) { return Math.cos(a) * x - Math.sin(a) * y; } function rotY(x, y, a) { return Math.sin(a) * x + Math.cos(a) * y; } function getY(oy, cr, dir, offset, a) { return oy + dir * Math.sin(offset + a * Math.PI*2) * cr; } function drawDNA(turtle, x, y, w, h) { turtle.down(); const offset = random() * Math.PI * 2; const ox = x + w/2; const oy = y + h/2; const cr = w / (5 + 10 * random()); const r = 0.0025 * w; const aa = random() * Math.PI * 2; const step = 1/(50 + 30 * random()); const freq = 3; const w2 = w * 1.3; const factor = 1 + random() * 2; [-1, 1].forEach(dir => { var previous = false; var index = -2; for (var a=0; a<1+step/2; a+=step) { const x2 = ox - w2 / 2 + w2 * a; const y2 = getY(oy, cr, dir, offset, a * factor); const rx = rotX(x2 - ox, y2 - oy, aa) + ox; const ry = rotY(x2 - ox, y2 - oy, aa) + oy; const current = [rx, ry]; if (previous) { turtle.jump(previous); turtle.goto(current); } previous = current; if ((index%freq)==0) { turtle.jump(rx, ry-r*5); turtle.circle(r*5); if (dir == 1) { const y3 = getY(oy, cr, -dir, offset, a * factor); const rx2 = rotX(x2 - ox, y3 - oy, aa) + ox; const ry2 = rotY(x2 - ox, y3 - oy, aa) + oy; turtle.jump(rx2, ry2); turtle.goto(rx, ry); } } else { turtle.jump(rx, ry-r*2); turtle.circle(r*2); } index++; } }); } function drawChart(turtle, x, y, w, h) { const cx = x + w * 0.1; const cw = w * 0.8; const cy = y + h * 0.9; const ch = -h * 0.8; turtle.down(); turtle.jump(cx, cy+ch); turtle.goto(cx, cy-ch * 0.1); turtle.jump(cx-cw * 0.1, cy); turtle.goto(cx+cw, cy); for (var fy=.3; fy<.91; fy+=.3) { const step = 1/40; turtle.up(); for (var fx=0, d=true; fx<1.01; fx+=step, d=!d) { turtle.goto(cx + fx * cw, cy + fy * ch); d ? turtle.down() : turtle.up(); } } { const step = 1/10; const tw = cw * 0.025; turtle.down(); for (var t=step; t<1; t+=step) { turtle.jump(cx + t * cw, cy + tw); turtle.goto(cx + t * cw, cy - tw); turtle.jump(cx - tw, cy + t * ch); turtle.goto(cx + tw, cy + t * ch); } } turtle.up(); const phase = random(); const step = 1/100; for (var fx=0; fx<1.01; fx+=step) { const fy = .5 + (Math.cos((fx + phase) * Math.PI * 2) / 2 + Math.cos((fx + phase) * Math.PI * 2 * 2 + phase) / 4 + Math.cos(fx * Math.PI * 2 * 4 + phase) / 8) /2; turtle.goto(cx + fx * cw, cy + fy * ch); turtle.down(); } } function drawPaper(turtle, width, height, pages) { const x = turtle.position()[0], y = turtle.position()[1]; const step = height / 200; turtle.down(); [[1,0],[1,1],[0,1],[0,0]].forEach(p => turtle.goto(x + width * p[0], y + height * p[1])); for (var p=1; p<pages; p++) { turtle.up(); [[1,1,0,0],[1,0,0,0],[1,0,1,0],[0,0,1,0],[0,0,1,1]].forEach(q => { turtle.goto(x + width * q[0] + step * (p - q[1]), y + height * q[2] + step * (p - q[3])); turtle.down(); }); } } //function random() { return Math.random(); } function random() { return rng.nextFloat(); } function generateRandomText(line_count, line_width) { var str = ""; for (var line=0; line<line_count; line++) { if (line > 0) str += '\n'; var need_space = 0; for (var c=0; c<line_width; c++) { if (c == line_width-1) need_space = 0; if (need_space > 1 && random()<0.2) { str += " "; need_space = 0; } else { str += String.fromCharCode(33 + (random()*94)|0); need_space++; } } } return str; } function FakeText() { var font = null; function generate_font() { if (font != null) return; font = {}; for (var c=33; c<127; c++) { font[c] = []; const count = 2 + random() * 8; const h = count / 20 + random() * 0.5; for (var i=0; i<count; i++) { const line = [ [ random(), 1 - random() * h], [ random(), 1 - random() * h] ]; font[c].push(line); } } } function print_chr(turtle, x, y, chr, char_width, char_height) { turtle.down(); const list = font[chr.charCodeAt(0)]; if (list !== undefined) { list.forEach(line => { turtle.jump(x + line[0][0] * char_width * 1.1, y + line[0][1] * char_height); turtle.goto(x + line[1][0] * char_width * 1.1, y + line[1][1] * char_height); }); } } function print_str(turtle, str, size=10) { generate_font(); str = str.toLowerCase(); const char_height = size; const char_width = size; var x = turtle.position()[0]; const left_x = x; var y = turtle.position()[1]; for (var i=0; i<str.length; i++) { if (str[i] == '\n') { x = left_x; y += char_height; } else { print_chr(turtle, x, y, str[i], char_width*1.2, char_height); x += char_width; } } turtle.jump(x, y); } return { print: (turtle, str, size) => print_str(turtle, str, size), }; } /////////////////////////////////////////////////////////////////////////// // Clipping Turtle utility code (minified). Created by Lionel Lemarie 2021 // https://turtletoy.net/turtle/2b46e93a22 /////////////////////////////////////////////////////////////////////////// function ClippingTurtle(){function i(i,s,t){return i-1e-4<=s&&s<=t+1e-4||t-1e-4<=s&&s<=i+1e-4}return new class extends Turtle{constructor(){super(),this.window=[],this.drawInsideWindow=!0}setWindow(i,s,t,n){this.window=[i,s,t,n]}drawWindow(){if(4!=this.window.length)return;const i=this.position(),s=!this.isdown();this.down(),super.jump(this.window[0],this.window[1]),super.goto(this.window[2],this.window[1]),super.goto(this.window[2],this.window[3]),super.goto(this.window[0],this.window[3]),super.goto(this.window[0],this.window[1]),super.jump(i),s&&this.up()}pointInside(i){return i[0]>=this.window[0]&&i[1]>=this.window[1]&&i[0]<=this.window[2]&&i[1]<=this.window[3]}lineInside(i){return this.pointInside(i[0])&&this.pointInside(i[1])}lineOutside(i){return i[0][0]<this.window[0]&&i[1][0]<this.window[0]||i[0][1]<this.window[1]&&i[1][1]<this.window[1]||i[0][0]>this.window[2]&&i[1][0]>this.window[2]||i[0][1]>this.window[3]&&i[1][1]>this.window[3]}clipLine(s,t,n,o,w){const e=(h=this.window[t],d=this.window[n],r=this.window[o],p=this.window[w],u=s[0][0],a=s[0][1],c=s[1][0],l=s[1][1],g=((h*p-d*r)*(u-c)-(h-r)*(u*l-a*c))/((h-r)*(a-l)-(d-p)*(u-c)),I=((h*p-d*r)*(a-l)-(d-p)*(u*l-a*c))/((h-r)*(a-l)-(d-p)*(u-c)),!(isNaN(g)||isNaN(I)||!i(h,g,r)||!i(d,I,p)||!i(u,g,c)||!i(a,I,l))&&[g,I]);var h,d,r,p,u,a,c,l,g,I;return e&&(s[this.pointInside(s[0])^this.drawInsideWindow?0:1]=[...e]),s}goto(i,s){const t=Array.isArray(i)?[...i]:[i,s];if(this.isdown()&&4==this.window.length){var n=[this.position(),[...t]];this.lineInside(n)?this.drawInsideWindow?super.goto(t):super.jump(t):this.lineOutside(n)?this.drawInsideWindow?super.jump(t):super.goto(t):(n=this.clipLine(n,0,1,2,1),n=this.clipLine(n,2,1,2,3),n=this.clipLine(n,0,3,2,3),n=this.clipLine(n,0,1,0,3),super.jump(n[0]),super.goto(n[1]),super.jump(t))}else super.goto(t)}circle(i){const s=this.position(),t=2*Math.PI/100;for(var n=-Math.PI/2;n<=1.501*Math.PI;n+=t)this.goto(s[0]+i*Math.cos(n),s[1]+i+i*Math.sin(n))}}} // Minified Random Number Generator from https://turtletoy.net/turtle/ab7a7e539e function RNG(t){return new class{constructor(t){this.m=2147483648,this.a=1103515245,this.c=12345,this.state=t||Math.floor(Math.random()*(this.m-1))}nextFloat(){return this.state=(this.a*this.state+this.c)%this.m,this.state/(this.m-1)}}(t)}