Skip to content

Instantly share code, notes, and snippets.

@AnastasiaDunbar
Last active August 12, 2021 14:25
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save AnastasiaDunbar/b7892e8e7d93143f2f51eab3a7180746 to your computer and use it in GitHub Desktop.
Save AnastasiaDunbar/b7892e8e7d93143f2f51eab3a7180746 to your computer and use it in GitHub Desktop.
function clamp(x,minVal,maxVal){return Math.min(Math.max(x,minVal),maxVal);}
function pointInRect(px,py,x,y,w,h){return px>=x&&py>=y&&px<x+w&&py<y+h;}
function drawASCIItable(x,y,w,h,columns=8,fromChar=32,toChar=126){
stroke(255);noFill();
rect(x,y,w,h);
if(user.click){user.ASCIItableClicked=pointInRect(mouseX,mouseY,x,y,w,h);}
var charCount=(toChar-fromChar)+1;
for(var i=1;i<columns;i++){
line(x+(i/columns)*w,y,x+(i/columns)*w,y+h);
}
var rows=columns>=1?Math.ceil(charCount/columns):charCount,
missing=(rows*columns)-charCount,
ylp=13;
for(var i=0;i<rows;i++){
var yl=y+(i/rows)*h;
line(x,yl,x+w,yl);
yl+=ylp;
line(x,yl,i===rows-1?(x+w)-((w/columns)*missing):x+w,yl);
}
if(missing){
noStroke();fill(255,32);
rect((x+w)-((missing/columns)*w),(y+h)-(h/rows),(missing/columns)*w,h/rows);
}
noStroke();fill(255);
textAlign(CENTER,TOP);textSize(10);
for(var yi=0;yi<rows;yi++){
for(var xi=0;xi<columns;xi++){
if((yi===rows-1)&&((yi*columns)+xi>=charCount)){break;}
text(
String.fromCharCode(fromChar+(yi*columns)+xi),
x+((xi+0.5)*(w/columns))-.5,
y+(yi*(h/rows))+2
);
if(fromChar+(yi*columns)+xi in myFont.render){
image(
myFont.render[fromChar+(yi*columns)+xi],
Math.floor(x+((xi+0.5)*(w/columns))-((myFont.w*myFont.renderSize)/2))-0.5,
Math.floor(y+(ylp/2)+((yi+0.5)*(h/rows))-((myFont.h*myFont.renderSize)/2))-0.5
);
}
}
}
if(pointInRect(mouseX,mouseY,x,y,w,h)){
noStroke();fill(255,64);
var s=clamp(Math.floor((mouseY-y)/(h/rows)),0,rows-1)*columns;
s+=clamp(Math.floor((mouseX-x)/(w/columns)),0,columns-1);
if(s<charCount){
rect(x+((s%columns)*(w/columns)),y+(Math.floor(s/columns)*(h/rows)),w/columns,h/rows);
if(user.ASCIItableClicked&&mouseIsPressed){user.currentChar=fromChar+s;}
}
}
stroke(255,0,0);noFill();
var s=user.currentChar-fromChar;
rect(
x+((s%columns)*(w/columns)),
y+(Math.floor(s/columns)*(h/rows)),
w/columns,h/rows
);
}
var user={
click:false,releaseClick:false,
currentChar:65,
ASCIItableClicked:false,
editorClicked:false,
pen:1
};
function mousePressed(){user.click=true;}
function mouseReleased(){user.releaseClick=true;}
var myFont={
w:3,h:5,char:{},render:{},renderSize:3
};
function renderChar(char){
if(!(char in myFont.render)){
myFont.render[char]=createGraphics(myFont.w*myFont.renderSize,myFont.h*myFont.renderSize);
}
if(myFont.render[char].width!==myFont.w*myFont.renderSize||myFont.render[char].height!==myFont.h*myFont.renderSize){
myFont.render[char].resizeCanvas(myFont.w*myFont.renderSize,myFont.h*myFont.renderSize);
}
myFont.render[char].clear();
//myFont.render[char].fill(255);
for(var yi=0;yi<myFont.h;yi++){
for(var xi=0;xi<myFont.w;xi++){
if(myFont.char[char][yi][xi]){
myFont.render[char].drawingContext.fillRect(
xi*myFont.renderSize,
yi*myFont.renderSize,
myFont.renderSize,
myFont.renderSize
);
}
}
}
}
function drawEditor(x,y,pixelSize){
stroke(255);noFill();
rect(x,y,myFont.w*pixelSize,myFont.h*pixelSize);
var pointInEditor=pointInRect(mouseX,mouseY,x,y,myFont.w*pixelSize,myFont.h*pixelSize);
if(user.click){user.editorClicked=pointInEditor;}
if(user.editorClicked){
if(!(user.currentChar in myFont.char)){
myFont.char[user.currentChar]=[];
for(var yi=0;yi<myFont.h;yi++){
myFont.char[user.currentChar][yi]=[];
for(var xi=0;xi<myFont.w;xi++){
myFont.char[user.currentChar][yi].push(0);
}
}
}
}
if(user.currentChar in myFont.char){
noStroke();fill(255);
if(user.editorClicked&&mouseIsPressed&&pointInEditor){
var mx=clamp(Math.floor((mouseX-x)/pixelSize),0,myFont.w-1),
my=clamp(Math.floor((mouseY-y)/pixelSize),0,myFont.h-1);
if(user.click){user.pen=myFont.char[user.currentChar][my][mx]?0:1;}
myFont.char[user.currentChar][my][mx]=user.pen;
renderChar(user.currentChar);
}
for(var yi=0;yi<myFont.h;yi++){
for(var xi=0;xi<myFont.w;xi++){
if(myFont.char[user.currentChar][yi][xi]){
rect(x+(xi*pixelSize),y+(yi*pixelSize),pixelSize,pixelSize);
}
}
}
}
stroke(255,user.currentChar in myFont.char?128:32);
for(var i=1;i<myFont.w;i++){line(x+(i*pixelSize),y,x+(i*pixelSize),y+(myFont.h*pixelSize));}
for(var i=1;i<myFont.h;i++){line(x,y+(i*pixelSize),x+(myFont.w*pixelSize),y+(i*pixelSize));}
}
class Button{
constructor(string,x,y,w,h,f){
this.x=x;this.y=y;
this.w=w;this.h=h;
this.string=string;
this.hold=false;
this.f=f;
}
render(){
var inside=pointInRect(mouseX,mouseY,this.x,this.y,this.w,this.h);
stroke(255);fill(inside?64:0);
rect(this.x,this.y,this.w,this.h);
noStroke();fill(255);
textAlign(CENTER,CENTER);textSize(12);
text(this.string,this.x+(this.w/2),this.y+(this.h/2));
if(inside&&user.click){
this.hold=true;
}
if(this.hold&&user.releaseClick){
if(inside){
this.f();
}
this.hold=false;
}
}
}
function pointInCircle(px,py,x,y,d){return Math.hypot(x-px,y-py)<(d/2);}
class Stepper{
constructor(string,value,x,y,f=()=>{},min=1,max=16){
this.string=string;this.value=value;this.x=x;this.y=y;
this.f=f;
this.min=min;this.max=max;
this.hover=0;
//this.hold=0; (this.value would react upon this as well)
}
render(){
stroke(255);
var s=20,d=14,i=(d/2)-3;
this.hover=pointInCircle(mouseX,mouseY,this.x+s,this.y,d)?1:(pointInCircle(mouseX,mouseY,this.x-s,this.y,d)?-1:0);
fill((this.hover===-1)*128);
circle(this.x-s,this.y,d);
line((this.x-s)-i,this.y,(this.x-s)+i,this.y);
fill((this.hover===1)*128);
circle(this.x+s,this.y,d);
line((this.x+s)-i,this.y,(this.x+s)+i,this.y);
line(this.x+s,this.y-i,this.x+s,this.y+i);
if(this.hover!==0&&user.click){
this.value=Math.max(Math.min(this.value+this.hover,this.max),this.min);
this.f(this.value);
}
noStroke();fill(255);
textAlign(CENTER,CENTER);textSize(16);
text(this.value,this.x,this.y+1);
textAlign(RIGHT,CENTER);
text(this.string+": ",this.x-(s+(d/2)),this.y+1);
}
}
function exportFont(){
var char=Object.entries(myFont.char).map(
e=>[String.fromCharCode(e[0]),e[1].map(a=>a.reduce((b,c,i)=>b|(c<<i),0))]
);
console.log(JSON.stringify({width:myFont.w,height:myFont.h,font:Object.fromEntries(char)}));
}
function numberTo1BitArray(n,s){for(var a=[],i=0;i<s;i++){a[i]=n&1<<i?1:0;}return a;}
function importFont(object){
myFont.w=object.width;myFont.h=object.height;
var char=Object.entries(object.font).map(
e=>[e[0].charCodeAt(0),e[1].map(a=>numberTo1BitArray(a,object.width))]
);
myFont.char=Object.fromEntries(char);
Object.keys(myFont.char).forEach(x=>{renderChar(x);});
}
function createArray(s,v){for(var f=(typeof v==="function"),a=[],i=0;i<s;i++){a[i]=f?v(i):v;}return a;}
var expButton,newButton,delButton,copyButton,pasteButton,charCopy,
wStepper,hStepper;
function setup(){
createCanvas(windowWidth,windowHeight);
expButton=new Button("Export",16,16+704+2,192,16,exportFont);
importFont({
"width":3,"height":5,"font":{
"0":[7,5,5,5,7],"1":[2,3,2,2,7],"2":[3,4,2,1,7],"3":[3,4,2,4,3],
"4":[5,5,7,4,4],"5":[7,1,3,4,3],"6":[6,1,7,5,7],"7":[7,4,2,2,2],
"8":[7,5,7,5,7],"9":[7,5,7,4,3],"!":[2,2,2,0,2],"\"":[5,5,0,0,0],
"#":[5,7,5,7,5],"$":[6,3,6,3,2],"%":[5,4,2,1,5],"&":[3,3,6,5,7],
"'":[2,2,0,0,0],"(":[4,2,2,2,4],")":[1,2,2,2,1],"*":[5,2,5,0,0],
"+":[0,2,7,2,0],",":[0,0,0,2,1],"-":[0,0,7,0,0],".":[0,0,0,0,2],
"/":[4,4,2,1,1],":":[0,2,0,2,0],";":[0,2,0,2,1],"<":[4,2,1,2,4],
"=":[0,7,0,7,0],">":[1,2,4,2,1],"?":[3,4,2,0,2],"@":[2,5,7,1,6],
"A":[2,5,7,5,5],"B":[3,5,3,5,3],"C":[6,1,1,1,6],"D":[3,5,5,5,3],
"E":[7,1,7,1,7],"F":[7,1,7,1,1],"G":[6,1,5,5,6],"H":[5,5,7,5,5],
"I":[7,2,2,2,7],"J":[4,4,4,5,2],"K":[5,5,3,5,5],"L":[1,1,1,1,7],
"M":[7,7,5,5,5],"N":[3,5,5,5,5],"O":[2,5,5,5,2],"P":[3,5,3,1,1],
"Q":[2,5,5,3,6],"R":[3,5,3,5,5],"S":[6,1,2,4,3],"T":[7,2,2,2,2],
"U":[5,5,5,5,7],"V":[5,5,5,5,2],"W":[5,5,5,7,7],"X":[5,5,2,5,5],
"Y":[5,5,2,2,2],"Z":[7,4,2,1,7],"[":[6,2,2,2,6],"\\":[1,1,2,4,4],
"]":[3,2,2,2,3],"^":[2,5,0,0,0],"_":[0,0,0,0,7],"`":[1,2,0,0,0],
"a":[0,0,3,4,7],"b":[1,1,3,5,3],"c":[0,0,6,1,6],"d":[4,4,6,5,6],
"e":[0,0,7,1,6],"f":[4,2,7,2,2],"g":[0,0,7,4,3],"h":[1,1,3,5,5],
"i":[2,0,3,2,2],"j":[2,0,2,2,1],"k":[1,1,5,3,5],"l":[3,2,2,2,4],
"m":[0,0,7,7,5],"n":[0,0,3,5,5],"o":[0,0,2,5,2],"p":[0,0,7,7,1],
"q":[0,0,7,7,4],"r":[0,0,5,3,1],"s":[0,0,6,2,3],"t":[2,2,7,2,4],
"u":[0,0,5,5,7],"v":[0,0,5,5,2],"w":[0,0,5,7,7],"x":[0,0,5,2,5],
"y":[0,0,5,6,3],"z":[0,0,3,2,6],"{":[6,2,3,2,6],"|":[2,2,2,2,2],
"}":[3,2,6,2,3],"~":[0,4,7,1,0]
}});
newButton=new Button("New",16,16+704+2+16+2,192,16,()=>{
myFont.char={};myFont.render={};
});
var x=16+192+2,y=16+17; //16+17+2+(64*myFont.h)
delButton=new Button("Delete",x,y,70,16,()=>{
delete myFont.char[user.currentChar];
delete myFont.render[user.currentChar];
});
x+=72;
copyButton=new Button("Copy",x,y,70,16,()=>{
charCopy=JSON.stringify(myFont.char[user.currentChar]);
});
x+=72;
pasteButton=new Button("Paste",x,y,70,16,()=>{
if(charCopy){
myFont.char[user.currentChar]=JSON.parse(charCopy);
renderChar(user.currentChar);
}
});
x=16+192+2+85;
y+=16+9;
wStepper=new Stepper("Width",myFont.w,x,y,value=>{
myFont.w=value;
for(var c in myFont.char){
myFont.char[c].forEach(a=>{
if(myFont.w>a.length){
a.push(0);
}else if(myFont.w<a.length){
a.pop();
}
});
renderChar(c);
}
});
y+=16;
hStepper=new Stepper("Height",myFont.h,x,y,value=>{
myFont.h=value;
for(var c in myFont.char){
if(myFont.h>myFont.char[c].length){
myFont.char[c].push(createArray(myFont.w,0));
}else if(myFont.h<myFont.char[c].length){
myFont.char[c].pop();
}
renderChar(c);
}
});
}
function drawFont(string,x,y,size=1){
noStroke();
var xs=0,ys=0;
for(var c,i=0;i<string.length;i++){
c=string.charCodeAt(i);
if(c in myFont.char){
for(var yi=0;yi<myFont.h;yi++){
for(var xi=0;xi<myFont.w;xi++){
if(myFont.char[c][yi][xi]){
drawingContext.fillRect(x+(((xs*(myFont.w+1))+xi)*size),y+(((ys*(myFont.h+1))+yi)*size),size,size);
}
}
}
}
if(string[i]==="\n"){
xs=0;ys++;
}else{
xs++;
}
}
}
function draw(){
background(0);
translate(.5,.5);
drawASCIItable(16,16,192,704,6);
noStroke();fill(255);
textAlign(LEFT,TOP);textSize(16);
text(`Current character: ${String.fromCharCode(user.currentChar)} (${user.currentChar})`,16+192+2,16);
drawEditor(16+192+2,16+17+51,64);
expButton.render();
newButton.render();
delButton.render();
copyButton.render();
pasteButton.render();
wStepper.render();hStepper.render();
drawFont("A quick brown fox jumps over the lazy dog.\nA QUICK BROWN FOX JUMPS OVER THE LAZY DOG!",450-.5,16-.5,2);
user.click=false;user.releaseClick=false;
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment