diff --git a/README.md b/README.md index fbf0697..4a165de 100644 --- a/README.md +++ b/README.md @@ -1,5 +1,69 @@ -# 12 Lines -12 Lines Font utilizes a 3-column-3-row grid as start and end points for 6 vertical and 6 horizontal segments of lines that are allowed to join these points in the shortest way possible. +# 12-Bit +12-Bit font utilizes a 3-column-3-row grid as start and end points for 6 vertical and 6 horizontal segments of lines that are allowed to join these points in the shortest way possible. With this concept in mind, out of 2^12 = 4096 signs available, only some were carefully chosen to represent all large and small characters of the standard Latin alphabet. Enjoy! [Demo](https://herbowicz.github.io/12/) (start typing, try w/caps lock too) + +## Sample text +![sample text](image.png) + +## Letters and numbers +![alt text](signs.png) + +Different font widths can obscure readability. +![alt text](font-width.png) + +## A Unique Approach to Cryptography and Design + +**A novel approach to representing characters using a minimal set of lines.** + +This project explores the concept of the 12-Bit font, a unique way to represent characters using a binary code and basic line segments. This approach offers exciting possibilities in cryptography, design, and other security applications. + +### How it Works + +1. **Character Representation:** + +Each character is represented by a 12-bit binary code. Each bit corresponds to a specific line segment within a 3x3 grid. + +``` +[1, 1, 1, 1, 0, 0, 1, 1, 0, 0, 1, 1] // A +[1, 0, 1, 1, 1, 1, 1, 1, 1, 0, 0, 1] // B +[1, 1, 0, 0, 1, 1, 1, 1, 0, 0, 0, 0] // C +``` + +2. **Canvas Rendering:** + +The binary code is used to determine which line segments to draw on a canvas. For example, the first bit indicates whether the top horizontal line should be drawn. + +```javascript +ctx.moveTo(s+l,s+d); if (sign[at][0]) { ctx.lineTo(s*2+l,s+d); }  +ctx.moveTo(s*2+l,s+d); if (sign[at][1]) { ctx.lineTo(s*3+l,s+d); } +// ... +``` + +### Benefits and Applications + +1. **Cryptography:** + +* **Steganography:** Embed information within images or other media using the minimalist nature of the font. +* **Security Tokens:** Create unique visual patterns for security tokens or watermarks. +* **Cryptography:** Utilize the binary representation as input for cryptographic algorithms. + +2. **Design:** + +* **Unique Typography:** Add a distinctive aesthetic to design projects with the font's style. +* **Minimalist Design:** Align your project with minimalist design principles using the font's simplicity. +* **Interactive Art:** Create interactive art installations or digital experiences with the font. + +3. **Accessibility:** + +* **Simplified Character Recognition:** The reduced number of elements can make character recognition easier for certain applications, such as OCR. +* **Universal Design:** Adapt the font for various screen sizes and resolutions due to its simplicity. + +### Future Directions + +* **Dynamic Font Generation:** Explore techniques to generate custom fonts based on specific design constraints or security requirements. +* **Font Optimization:** Optimize the font for different rendering contexts, such as web, print, and mobile devices. +* **Security Analysis:** Conduct a thorough security analysis to identify potential vulnerabilities and strengthen the font's security properties. + +The 12-Bit font offers a promising approach with potential applications in various fields. By leveraging its unique characteristics, we can unlock new possibilities for creative endeavors and security advancements. diff --git a/font-width.png b/font-width.png new file mode 100644 index 0000000..af7b07f Binary files /dev/null and b/font-width.png differ diff --git a/image.png b/image.png new file mode 100644 index 0000000..321a108 Binary files /dev/null and b/image.png differ diff --git a/index.html b/index.html index 5e24ee6..14687a5 100644 --- a/index.html +++ b/index.html @@ -1,196 +1,28 @@ - - - - - - -
Width: Size:
- - - - + + + + + + + 12-Bit + + + + +
+ Width: + + + +
+
+ Size: + + + +
+ + + + + \ No newline at end of file diff --git a/script.js b/script.js new file mode 100644 index 0000000..3cb08f4 --- /dev/null +++ b/script.js @@ -0,0 +1,190 @@ +let canvas = document.getElementById("canvas"); +let ctx = canvas.getContext("2d"); +canvas.width = window.innerWidth; +canvas.height = window.innerHeight; + +const sign = { + "!": [1, 1, 1, 1, 0, 0, 1, 0, 0, 1, 1, 0], //! + "\"": [0, 0, 0, 0, 0, 0, 1, 0, 1, 0, 0, 0], //" + "#": [1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1], //# + "$": [1, 1, 1, 1, 1, 1, 1, 0, 1, 1, 0, 1], //$ + "%": [0, 1, 1, 1, 1, 0, 0, 1, 1, 1, 1, 0], //% + "&": [1, 0, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0], //& + "'": [0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0], //' + "(": [1, 0, 0, 0, 1, 0, 1, 1, 0, 0, 0, 0], //( + ")": [0, 1, 0, 0, 0, 1, 0, 0, 0, 0, 1, 1], //) + "*": [0, 0, 1, 1, 0, 0, 1, 1, 1, 1, 1, 1], //* + "+": [0, 0, 1, 1, 0, 0, 0, 0, 1, 1, 0, 0], //+ + ",": [0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0], //, + "-": [0, 0, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0], //- + ".": [0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0], //. + "/": [0, 1, 1, 1, 1, 0, 0, 1, 1, 1, 1, 0], /// + "0": [1, 1, 0, 0, 1, 1, 1, 1, 1, 1, 1, 1], //0 + "1": [1, 0, 0, 0, 1, 1, 0, 0, 1, 1, 0, 0], //1 + "2": [1, 0, 1, 0, 1, 1, 0, 1, 1, 0, 0, 0], //2 + "3": [1, 1, 0, 1, 1, 1, 0, 0, 0, 0, 1, 1], //3 + "4": [0, 0, 1, 1, 0, 0, 1, 0, 0, 0, 1, 1], //4 + "5": [0, 1, 0, 1, 1, 1, 0, 0, 1, 0, 0, 1], //5 + "6": [1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0, 1], //6 + "7": [1, 1, 0, 0, 0, 0, 1, 0, 0, 0, 1, 1], //7 + "8": [1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 1, 1], //8 + "9": [1, 1, 1, 1, 1, 1, 1, 0, 0, 0, 1, 1], //9 + ":": [0, 0, 1, 0, 1, 0, 0, 0, 0, 0, 0, 0], //: + ";": [1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 0, 0], //; + "<": [0, 1, 1, 0, 0, 1, 0, 0, 1, 1, 0, 0], //< + "=": [0, 0, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0], //= + ">": [1, 0, 0, 1, 1, 0, 0, 0, 1, 1, 0, 0], //> + "?": [1, 1, 0, 1, 0, 0, 0, 0, 0, 1, 1, 0], //? + "@": [1, 1, 1, 0, 1, 1, 0, 1, 0, 1, 1, 1], //@ + "A": [1, 1, 1, 1, 0, 0, 1, 1, 0, 0, 1, 1], //A + "B": [1, 0, 1, 1, 1, 1, 1, 1, 1, 0, 0, 1], //B + "C": [1, 1, 0, 0, 1, 1, 1, 1, 0, 0, 0, 0], //C + "D": [1, 0, 0, 1, 1, 1, 1, 1, 1, 0, 0, 1], //D + "E": [1, 1, 1, 0, 1, 1, 1, 1, 0, 0, 0, 0], //E + "F": [1, 1, 1, 0, 0, 0, 1, 1, 0, 0, 0, 0], //F + "G": [1, 1, 0, 1, 1, 1, 1, 1, 0, 0, 0, 1], //G + "H": [0, 0, 1, 1, 0, 0, 1, 1, 0, 0, 1, 1], //H + "I": [1, 1, 0, 0, 1, 1, 0, 0, 1, 1, 0, 0], //I + "J": [1, 1, 0, 0, 1, 1, 0, 1, 0, 0, 1, 1], //J + "K": [0, 1, 1, 0, 0, 1, 1, 1, 1, 1, 0, 0], //K + "L": [0, 0, 0, 0, 1, 1, 1, 1, 0, 0, 0, 0], //L + "M": [1, 1, 0, 0, 0, 0, 1, 1, 1, 0, 1, 1], //M + "N": [1, 0, 0, 0, 0, 1, 1, 1, 1, 1, 1, 1], //N + "O": [1, 1, 0, 0, 1, 1, 1, 1, 0, 0, 1, 1], //O + "P": [1, 1, 1, 1, 0, 0, 1, 1, 0, 0, 1, 0], //P + "Q": [1, 1, 1, 1, 0, 1, 1, 0, 0, 1, 1, 0], //Q + "R": [1, 1, 1, 1, 0, 1, 1, 1, 0, 1, 1, 0], //R + "S": [1, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 1], //S + "T": [1, 1, 0, 0, 0, 0, 0, 0, 1, 1, 0, 0], //T + "U": [0, 0, 0, 0, 1, 1, 1, 1, 0, 0, 1, 1], //U + "V": [0, 0, 0, 1, 1, 0, 1, 1, 0, 1, 1, 0], //V + "W": [0, 0, 0, 0, 1, 1, 1, 1, 0, 1, 1, 1], //W + "X": [0, 0, 1, 1, 0, 0, 1, 0, 1, 1, 0, 1], //X + "Y": [0, 0, 1, 1, 0, 0, 1, 0, 0, 1, 1, 0], //Y + "Z": [1, 1, 1, 1, 1, 1, 0, 1, 0, 0, 1, 0], //Z + "[": [1, 0, 0, 0, 1, 0, 1, 1, 0, 0, 0, 0], //[ + "\\": [1, 0, 1, 1, 0, 1, 1, 0, 1, 1, 0, 1], //\ + "]": [0, 1, 0, 0, 0, 1, 0, 0, 0, 0, 1, 1], //] + "^": [1, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0], //^ + "_": [0, 0, 0, 0, 1, 1, 0, 0, 0, 0, 0, 0], //_ + "`": [1, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0], //` + "a": [0, 0, 1, 0, 1, 1, 0, 1, 0, 1, 0, 0], //a + "b": [0, 0, 1, 1, 1, 1, 1, 1, 0, 0, 0, 1], //b + "c": [0, 0, 1, 1, 1, 1, 0, 1, 0, 0, 0, 0], //c + "d": [0, 0, 1, 1, 1, 1, 0, 1, 0, 0, 1, 1], //d + "e": [1, 0, 1, 0, 1, 1, 1, 1, 1, 0, 0, 0], //e + "f": [0, 1, 1, 1, 0, 0, 0, 0, 1, 1, 0, 0], //f + "g": [0, 1, 0, 1, 1, 1, 0, 0, 1, 0, 1, 1], //g + "h": [0, 0, 1, 1, 0, 0, 1, 1, 0, 0, 0, 1], //h + "i": [0, 0, 1, 1, 1, 1, 0, 0, 0, 1, 0, 0], //i + "j": [0, 0, 0, 0, 1, 1, 0, 0, 0, 0, 0, 1], //j + "k": [0, 0, 1, 1, 0, 1, 1, 1, 0, 1, 0, 0], //k + "l": [0, 0, 0, 0, 1, 1, 0, 1, 0, 0, 0, 0], //l + "m": [0, 0, 1, 1, 0, 0, 0, 1, 0, 1, 0, 1], //m + "n": [0, 0, 1, 1, 0, 0, 0, 1, 0, 0, 0, 1], //n + "o": [0, 0, 1, 1, 1, 1, 0, 1, 0, 0, 0, 1], //o + "p": [0, 1, 0, 1, 1, 0, 0, 0, 1, 1, 1, 0], //p + "q": [1, 0, 1, 0, 0, 1, 1, 0, 1, 1, 0, 0], //q + "r": [0, 0, 1, 1, 0, 0, 0, 1, 0, 0, 0, 0], //r + "s": [0, 0, 0, 1, 1, 0, 0, 0, 0, 1, 0, 0], //s + "t": [0, 0, 1, 1, 0, 1, 0, 0, 1, 1, 0, 0], //t + "u": [0, 0, 0, 0, 1, 1, 0, 1, 0, 0, 0, 1], //u + "v": [0, 0, 1, 0, 0, 1, 0, 0, 0, 1, 0, 1], //v + "w": [0, 0, 0, 0, 1, 1, 0, 1, 0, 1, 0, 1], //w + "x": [0, 0, 1, 1, 0, 0, 0, 1, 1, 1, 1, 0], //x + "y": [0, 0, 0, 1, 1, 1, 0, 0, 1, 0, 1, 1], //y + "z": [0, 0, 1, 0, 0, 1, 0, 0, 0, 1, 0, 0], //z + "{": [0, 1, 1, 0, 0, 1, 0, 0, 1, 1, 0, 0], //{ + "|": [0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 0, 0], //| + "}": [1, 0, 0, 1, 1, 0, 0, 0, 1, 1, 0, 0], //} + "~": [1, 0, 0, 1, 0, 0, 1, 0, 1, 0, 1, 0], //~ +} + +let l = 0; // left offset +let d = 0; // down offset +let w = 2; // width +let s = 12; // size +let on = true; +const widthSpan = document.querySelector('#width span'); +const sizeSpan = document.querySelector('#size span'); + +widthSpan.textContent = w; +sizeSpan.textContent = s; + +console.log(widthSpan.textContent, sizeSpan.textContent) + +document.querySelectorAll('button') + .forEach(el => el.addEventListener('click', (event) => { + + console.log(event.target.parentElement.id, event.target.className) + + if (event.target.parentElement.id === 'width') { + w = Math.max(1, w + Number(event.target.className)); + widthSpan.textContent = w; + } else if (event.target.parentElement.id === 'size') { + s = Math.max(1, s + Number(event.target.className)); + sizeSpan.textContent = s; + } + })) + +const clear = () => { + ctx.clearRect(s / 2 + l, s / 2 + d, s * 3, s * 3); +}; + +const cursor = () => { + if (on) { + clear(); + ctx.beginPath(); + ctx.lineWidth = w; + ctx.moveTo(s + l, s * 3 + d); + ctx.lineTo(s * 3 + l, s * 3 + d); + ctx.stroke(); + on = false; + } else { + clear(); + on = true; + } +} + +setInterval(cursor, 500); + +document.addEventListener('keydown', (event) => { + const key = event.key; + // console.log({ key }) + + clear(); + + if (key === 'Backspace') { // Backspace + l -= s * 3; + if (l < 0) { + l = 0; + } + } else if (key === 'Enter' || l >= canvas.width - s * 3) { // Enter or end of line + l = 0; + d += s * 3; + } else if (key === ' ') { // Space + l += s * 3; + } else { + ctx.beginPath(); + ctx.lineWidth = w; + + if (!sign[key]) return; + + //horizontal lines + ctx.moveTo(s + l, s + d); if (sign[key][0]) { ctx.lineTo(s * 2 + l, s + d); } + ctx.moveTo(s * 2 + l, s + d); if (sign[key][1]) { ctx.lineTo(s * 3 + l, s + d); } + ctx.moveTo(s + l, s * 2 + d); if (sign[key][2]) { ctx.lineTo(s * 2 + l, s * 2 + d); } + ctx.moveTo(s * 2 + l, s * 2 + d); if (sign[key][3]) { ctx.lineTo(s * 3 + l, s * 2 + d); } + ctx.moveTo(s + l, s * 3 + d); if (sign[key][4]) { ctx.lineTo(s * 2 + l, s * 3 + d); } + ctx.moveTo(s * 2 + l, s * 3 + d); if (sign[key][5]) { ctx.lineTo(s * 3 + l, s * 3 + d); } + //vertical lines + ctx.moveTo(s + l, s + d); if (sign[key][6]) { ctx.lineTo(s + l, s * 2 + d); } + ctx.moveTo(s + l, s * 2 + d); if (sign[key][7]) { ctx.lineTo(s + l, s * 3 + d); } + ctx.moveTo(s * 2 + l, s + d); if (sign[key][8]) { ctx.lineTo(s * 2 + l, s * 2 + d); } + ctx.moveTo(s * 2 + l, s * 2 + d); if (sign[key][9]) { ctx.lineTo(s * 2 + l, s * 3 + d); } + ctx.moveTo(s * 3 + l, s + d); if (sign[key][10]) { ctx.lineTo(s * 3 + l, s * 2 + d); } + ctx.moveTo(s * 3 + l, s * 2 + d); if (sign[key][11]) { ctx.lineTo(s * 3 + l, s * 3 + d); } + ctx.stroke(); + l += s * 3; + } +}); diff --git a/signs.png b/signs.png new file mode 100644 index 0000000..7263b37 Binary files /dev/null and b/signs.png differ diff --git a/style.css b/style.css new file mode 100644 index 0000000..9826ec0 --- /dev/null +++ b/style.css @@ -0,0 +1,12 @@ +body { + margin: 0 auto; + padding: 0; + overflow: hidden; + color: #222; + background-color: #ccc; +} + +div { + color: #222; + float: right; +} \ No newline at end of file