Bitmap Font Text 🗒️

A bitmap font based text utility that can be used to print text to the screen.
I added two bitmap fonts (tiny/normal) based on some images in some own format.

The letter- and line spacing can be set in the constructor.

There's a function to iterate over the pixels of the font to do custom stuff with it, like the third text does.

Kinda follows same API as Hello, world

#text #font #utility

Log in to post a comment.

const turtle = new Turtle();

function walk(i) {
    const text = new BitmapText(BitmapTextFonts.NORMAL);
    turtle.jump(-40, -30)
    text.print(turtle, "~ hello\nworld ~", 2, true,true);
    
    
    const text2 = new BitmapText(BitmapTextFonts.SMALL, 4);
    turtle.jump(-75, -70)
    text2.print(turtle, "0123456789!", 2);
    
    
    const text3 = new BitmapText(BitmapTextFonts.SMALL);
    const startPos = [-60, 40];
    text3.iter("~ hello world ~".toUpperCase(), pos => {
        const scale = 2;
        const p = [pos[0] * scale + startPos[0], pos[1] * scale + startPos[1]];
        turtle.jump(p[0], p[1]);
        turtle.circle(1.2);
        turtle.jump(p[0], p[1]);
        turtle.circle(1.0);
    });
}


////////////////////////////////////////////////////////////////
// BitmapText utility code. Created by Mark Knol 2020
// https://turtletoy.net/turtle/48b904349d
////////////////////////////////////////////////////////////////
class BitmapText {
    constructor(font, letterSpacing = 1, lineSpacing = 2) {
        this.font = font;
        this.letterSpacing = letterSpacing;
        this.lineSpacing = lineSpacing;
        
		// decode
        const data = this.font.data;
        this.bits = [];
    	let odd = true;
    	for(let ii=0; ii<data.length; ii++) {
    		for(let c=0;c<data.charCodeAt(ii) - 40; c++) {
    			this.bits.push(odd);
    		}
    		odd = !odd;
    	}
    }
    print(t, str, scale, diagonal1 = false, diagonal2 = false) {
        const startPos = t.pos();
        this.iter(str, pos => {
            const a = [pos[0] * scale, pos[1] * scale];
            const b = [(pos[0] + 1) * scale, (pos[1] + 1) * scale];
            a[0] += startPos[0];
            a[1] += startPos[1];
            b[0] += startPos[0];
            b[1] += startPos[1];
            t.jump(a[0], a[1]);
            t.goto(b[0], a[1]);
            t.goto(b[0], b[1]);
            t.goto(a[0], b[1]);
            t.goto(a[0], a[1]);
            if (diagonal1) t.goto(b[0], b[1]); 
            if (diagonal2) {
                t.jump(a[0], b[1]);
                t.goto(b[0], a[1]);
            }
        });
    }
    iter(str, cb) {
        this.get(str).forEach(cb);
    }
	get(str) {
		const positions = [];
		let line = 0;
        let offset = 0;
		const cpl = this.font.charsPerLine;
        for (let i=0; i<str.length; i++) {
            if (str.charAt(i) == "\n") { line ++; offset = 0; continue; }
            let char = str.charCodeAt(i) - 32; // start from space
            if (char < 0 || char > 3 * 32) continue;
            let drawPos = [offset++ * (this.font.size[0] + this.letterSpacing), line * (this.font.size[1] + this.lineSpacing)];
            let charPos = [char % cpl * (this.font.size[0] + this.font.spacing[0]), Math.floor(char / cpl) * (this.font.size[1] + this.font.spacing[1])];
            for (let y=0; y<this.font.size[1]; y++){
                for (let x=0; x<this.font.size[0]; x++) {
                    let dotPos = [x, y];
                    if (this.bits[charPos[0] + dotPos[0] + (charPos[1] + dotPos[1]) * ((this.font.size[0] + this.font.spacing[0]) * cpl)]) {
                        positions.push([drawPos[0] + dotPos[0], drawPos[1] + dotPos[1]]);
                    }
                }
            }
        }
		return positions;
	}
}

const BitmapTextFonts = {
    // based on <https://robey.lag.net/2010/01/23/tiny-monospace-font.html>
    SMALL: {
        data: "(-)*)))))))**)),)+),)))+)))=+*)*+)+)))))+)+)+)+)+3)-)++.)*))))+)*,)))))*)+)+)+)+)8)))))*),)+)))))))+)-)))))))))*)+)+)*+*),).).)))***)+)/)+)*+)+-+.)*)))*)*+**)+)+)++))+)+1)1)*)6+)**)+))).)+)+)+)+)/)*)+)))*)*)-)+)+)))))+)))))+)*)+)+)*+*)3).)))*),)**/)))+)))-)0).+*)*+)++))+)++))+)+-)-)-),)«)+)**+*)**+)+**)))))++)))))))+)))))))*)**+)**+*)+)))))))))))))))))))))+)+-+*).)))))))))))))+)))))+)+)+)))*),)))))))++)+)))))))))))))))))),)*)))))))))))))))))))+)))+)-)))))-+)+)**)+))))+)+)+)+*),))**)++)+)))))**))))+*)+)*))))))))+*)+)+)*),),)1)+)))))))))+)))))+)+)))))))*)*)))))))))+))))+))))))++)*,)*)*)))*)*+))))*)*)+)-)+)2*)))))*+*)**+)),*)))))+*)*))))+))))))))*)*),*)))))*+)+**)*)))))))*)*+)+-+-+©)/)1)/)-),),)-*G)C**)**+*)+*).)1)***)+*))3),)7)+)*),*)+9))))+*)+)+)***+.*)*+***)))))+)+)*+),)))))*)*+)*+)*))))))))+)*+)*)))))))))))))))****))1)-+-)))))))))+))))*+),)))))*),))*+)*+)))))))))*+*)),**)*))))+)+*),))*+)+)+).+-+)*+******)***)))*)***))))+))))))))*)*)-)))+*+)+**)*+)))))**+***)**.+©",
        size: [3,5],
        spacing: [1,1],
        charsPerLine: 32,
    },
    // based on <https://opengameart.org/content/ascii-bitmap-font-oldschool>
    NORMAL: {
        data: "(1)-))),)))-),*.+-)/),)X+-)5)-))),))),,***)*)*)-).).),))))),)E)*)+)+*5)3-*)))/)+)))4)0),+-)D)+)***)))5)4))),+-)-)5)0)+-*-1-3),))))),)5)3-,)))+)-)))))2)0),+-).);)-**),)B)))+,+)***)*)4).),))))),).):).)+),)5)4)))-)/*+*))4),)<)6)4++-ħ+,+-*+-+++-++,+O+,+,++,,++)+)*)+)+)))+).)2)*)+)*)+),).)/)3)-)+)*)+)*)+)*)+)*)+).).)*)*)+).)1)+)+)*)+):),-,),)+)*))+*)+)*)+)*)1)-*+-*,+,-)-+,,9)7).)+)))))*-*,+)0)0)-)/)*)+)+)-)+).)3).),-,).),))+*)+)*)+)*)/)-)+)-)/)*)+)+)-)+).),).)/)3)4).)+)*)+)*)+)*-++.)+,,+,).+,+3)D)-++)+)*,,+ħ,+-*-+++)+)*-*-*)+)*).)+)*)+)+++,,++,,,*-*)+)*)+)*).).)+)*)+),)0)*)+)*).*)**)+)*)+)*)+)*)+)*)+)*)0),)+)*)+)*).).).)+),)0)*)*)+).)))))***)*)+)*)+)*)+)*)+)*)0),)+)*)+)*,+,+).-,)0)*+,).)+)*)))))*)+)*,+)+)*,,+-),)+)*)+)*).).)***)+),)0)*)*)+).)+)*)***)+)*).)))))*)+).),),)+)*)+)*).).)+)*)+),),)+)*)+)*).)+)*)+)*)+)*).)*)+)+).),),)+)*,+-*)/++)+)*-+++)+)*-*)+)*)+)+++)/*))*)+)*,-)-+ħ)+)*)+)*)+)*)+)*-,*3*.)4)4)9)3*2)+)*)+)*)+)*)+).),),)0)-)))4)3)9)2)4)+)*)+)+))),))).)-)-)/)B++,,+,,+++-+,*)+)*)+),).).).).).)E)*)+)*)+)*)+)*)+)+)-)+)*)+)*)))))+)))-)-)/)/)-)B,*)+)*).)+)*-+).,+)))+*)**)+),),)0)0),)A)+)*)+)*)+)*)+)*)/)1),),)+)*)+),),-,*3*3-2,*,,+,,+,+).+ħ)0)0)*).)`)P)<).)`)P,++.+*)*)+).*))+,,++,,,*))*,,*,+)+)*)+)*)+)*)+)*)+)*)+),)0)*+,).)))))*)+)*)+)*)+)*)+)***)*)/)-)+)*)+)*)+)+)))+)+)*)+),)0)*)*)+).)))))*)+)*)+)*,,,*)/+,)-)+)*)+)*)+),)-,*)+),),)+)*)+)*).)+)*)+)*)+)*)2)*)2)+)*)*)+)+)))+)))))+)))/)*)+)*-+++)+)+++)+)*)+)+++)2)*).,-*,,,)-)))+)+)++ı)-)-)˜).).)Ž-,).).)-)*)ˆ),)/)/)+))*ˆ).).).))/).).)Ž--)-)-)Ƌ",
        size: [5,7],
        spacing: [2,2],
        charsPerLine: 18,
    }
}