Skip to content

Commit

Permalink
bitfont stuff
Browse files Browse the repository at this point in the history
  • Loading branch information
katsaii committed Feb 22, 2024
1 parent ed2674d commit 9fbdddf
Show file tree
Hide file tree
Showing 3 changed files with 84 additions and 17 deletions.
7 changes: 6 additions & 1 deletion bit-font.html
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,11 @@
<p>upload a json file exported from <a href="https://www.pentacom.jp/pentacom/bitfontmaker2/">Bit Font Maker 2</a> (using the <img style="vertical-align : middle" src="https://www.pentacom.jp/pentacom/bitfontmaker2/img/menu_data.gif"> "<code>Data Import/Export</code>" button)</p>
<input type="file" id="json-file">
<hr>
<label for="font-col">choose a colour for the font:</label>
<input id="font-col" type="color">
<hr>
<button onclick="bitFontIntoImage()">Bit Font Maker json -&gt; image</button>
<hr>
<div id="dest"></div>
<textarea id="dest-alphabet" cols="80" rows="3"></textarea>
<br>
<canvas id="dest-canvas"></canvas>
91 changes: 76 additions & 15 deletions bit-font.js
Original file line number Diff line number Diff line change
@@ -1,25 +1,86 @@
//a.files[0].arrayBuffer().then(x => {
// let tc = new TextDecoder("utf-8");
// console.log(tc.decode(x));
//})
const getFileBuffer = () => document.getElementById("json-file").files[0];
const setTextAlphabet = (value) => document.getElementById("dest-alphabet").value = value;
const isNumeric = (n) => !isNaN(n);
const dec2bin = (dec) => (dec >>> 0).toString(2);

const bitFontIntoImage = () => getFileBuffer().text().then((text) => {
const json = JSON.parse(text);
const FONT_CELL_SIZE = 16;

const extractFontPages = (json) => {
let font = [];
for (const charCode in json) {
if (!isNumeric(charCode)) {
continue;
}
const char = String.fromCharCode(charCode);
console.log(`"${charCode}" ${char}`);
const frameData = json[charCode];
let debugView = "";
for (const line of frameData) {
const bits = dec2bin(line);
debugView += bits.padStart(16, "0").split("").reverse().join("") + "\n";
}
console.log(debugView.replaceAll("0", " ").replaceAll("1", "■"));
font.push({
charCode,
char : String.fromCharCode(charCode),
lines : json[charCode],
});
}
return font;
};

const FONT_COL = { r : 0, g : 0, b : 0, a : 255 };
const FONT_COL_BG = { r : 0, g : 0, b : 0, a : 0 };

const refreshFontColour = () => {
const cssColour = document.getElementById("font-col").value;
FONT_COL.r = parseInt(cssColour.slice(1, 1 + 2), 16);
FONT_COL.g = parseInt(cssColour.slice(3, 3 + 2), 16);
FONT_COL.b = parseInt(cssColour.slice(5, 5 + 2), 16);
}

const setPixel = (iDest, imageData, { r, g, b, a }) => {
imageData.data[iDest + 0] = r;
imageData.data[iDest + 1] = g;
imageData.data[iDest + 2] = b;
imageData.data[iDest + 3] = a;
};

const setLine = (iDest, imageData, line) => {
const getPixelColour = (mask) => (line & mask) == 0 ? FONT_COL_BG : FONT_COL;
setPixel(iDest + 0 * 4, imageData, getPixelColour(0b0000_0000_0000_0001));
setPixel(iDest + 1 * 4, imageData, getPixelColour(0b0000_0000_0000_0010));
setPixel(iDest + 2 * 4, imageData, getPixelColour(0b0000_0000_0000_0100));
setPixel(iDest + 3 * 4, imageData, getPixelColour(0b0000_0000_0000_1000));
setPixel(iDest + 4 * 4, imageData, getPixelColour(0b0000_0000_0001_0000));
setPixel(iDest + 5 * 4, imageData, getPixelColour(0b0000_0000_0010_0000));
setPixel(iDest + 6 * 4, imageData, getPixelColour(0b0000_0000_0100_0000));
setPixel(iDest + 7 * 4, imageData, getPixelColour(0b0000_0000_1000_0000));
setPixel(iDest + 8 * 4, imageData, getPixelColour(0b0000_0001_0000_0000));
setPixel(iDest + 9 * 4, imageData, getPixelColour(0b0000_0010_0000_0000));
setPixel(iDest + 10 * 4, imageData, getPixelColour(0b0000_0100_0000_0000));
setPixel(iDest + 11 * 4, imageData, getPixelColour(0b0000_1000_0000_0000));
setPixel(iDest + 12 * 4, imageData, getPixelColour(0b0001_0000_0000_0000));
setPixel(iDest + 13 * 4, imageData, getPixelColour(0b0010_0000_0000_0000));
setPixel(iDest + 14 * 4, imageData, getPixelColour(0b0100_0000_0000_0000));
setPixel(iDest + 15 * 4, imageData, getPixelColour(0b1000_0000_0000_0000));
};

const copyFontPageToCanvas = (iDest, { lines }, imageData) => {
for (let iLine in lines) {
setLine(iDest + iLine * imageData.width * 4, imageData, lines[iLine]);
}
};

const bitFontIntoImage = () => getFileBuffer().text().then((text) => {
refreshFontColour();
const font = extractFontPages(JSON.parse(text));
const fontCellsPerRow = Math.ceil(Math.sqrt(font.length));
// get the canvas and resize it
const canvasSize = fontCellsPerRow * FONT_CELL_SIZE;
const canvas = document.getElementById("dest-canvas");
canvas.width = canvasSize; // need to resize the canvas otherwise the image won't fit
canvas.height = canvasSize;
// actually draw the image data
const canvasCtx = canvas.getContext("2d");
const imageData = canvasCtx.createImageData(canvasSize, canvasSize);
for (const iPage in font) {
const pageX = (iPage % fontCellsPerRow);
const pageY = Math.floor(iPage / fontCellsPerRow);
const iDest = pageY * imageData.width * 4 * 16 + pageX * 4 * 16;
copyFontPageToCanvas(iDest, font[iPage], imageData);
}
canvasCtx.putImageData(imageData, 0, 0);
setTextAlphabet(font.reduce((acc, { char }) => acc + char, ""));
});
3 changes: 2 additions & 1 deletion index.html
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,8 @@ <h1>Sick of brands?</h1>
<p>this site is an alternative to that, offering these bare bones tools with no
ads or surveillance</p>
<ul>
<li><a href="./bit-font.html">convert Bit Font Maker fonts into sprite atlases for use in GameMaker</a></li>
<li><a href="./word-count.html">word counter</a></li>
<li><a href="./morse-code.html">morse code encoder/decoder</a></li>
<li><a href="./morse-code.html">morse code decoder, encoder, and visualiser</a></li>
</ul>
<p>view the JavaScript code <a href="https://github.com/katsaii/sob/blob/main/sob">here</a></p>

0 comments on commit 9fbdddf

Please sign in to comment.