Constructing text with astericks
Adam D. Ruppe
destructionator at gmail.com
Thu May 31 16:49:00 UTC 2018
On Thursday, 31 May 2018 at 16:05:40 UTC, aberba wrote:
> That doesn't sound like a trivial thing to do. Ha ha
Oh, it isn't that bad if you can get a font as an image file (and
have the code to load such image files... but I do!)
Take a look at my little answer (SPOILERS THOUGH! Maybe skip to
bottom of this message if you don't want to actually see the
working answer just to get more help):
---
class Font {
import arsd.png;
enum charWidth = 8;
enum charHeight = 8;
TrueColorImage image;
// font.png is just a screenshot of monospaced font written out
in 8x8 cells
// (that's where the charWidth and charHeight things above come
from), one after
// another in the image
this() {
image = readPng("font.png").getAsTrueColorImage();
}
char[charWidth][charHeight] getChar(char c) {
// just finding the character offset in the image
auto entriesPerLine = image.width / charWidth;
auto charX = c % entriesPerLine;
auto charY = c / entriesPerLine;
auto xOffset = charX * charWidth;
auto yOffset = charY * charHeight;
char[charWidth][charHeight] buffer;
// then drawing it to the buffer
foreach(y; 0 .. charHeight) {
foreach(x; 0 .. charWidth) {
// if it is not transparent, use *, otherwise, use space.
buffer[y][x] = (image.getPixel(xOffset + x, yOffset + y).a >
0 ? '*' : ' ');
}
}
return buffer;
}
}
// this represents the screen. It is buffered so we can jump
around x and y to make
// lines of stars instead of trying to just do one line of font
"pixels" at a time...
char[70][24] screenBuffer;
int bufferCursorX;
int bufferCursorY;
// to draw an individual character, we loop through the character
and copy its pixels
// line by line...
void writeCharToBuffer(int x, int y,
char[Font.charWidth][Font.charHeight] ch) {
foreach(a; 0 .. Font.charHeight)
screenBuffer[y + a][x .. x + Font.charWidth] = ch[a][];
}
// and to write a string, we do the same for each char. This also
just keeps track
// of the cursor position so subsequent calls will add the chars
after the last ones.
//
// Note this may throw a RangeError when it runs out of space!!
void writeStringToBuffer(Font font, string str) {
foreach(char ch; str) {
writeCharToBuffer(bufferCursorX, bufferCursorY,
font.getChar(ch));
bufferCursorX += Font.charWidth;
if(bufferCursorX + Font.charWidth >
screenBuffer[bufferCursorY].length) {
// the next character would go off the screen, so wrap this
char
// to the next line
bufferCursorY += Font.charHeight;
bufferCursorX = 0;
}
}
}
// then once everything is buffered, writing it to the actual
screen
// is as simple as looping over the buffered lines and outputting
them!
void writeBufferToScreen() {
import std.stdio;
foreach(line; screenBuffer)
writeln(line);
}
void main() {
// clear the screen...
foreach(ref line; screenBuffer)
line[] = ' ';
// load the font
auto font = new Font();
// write our string to the buffer
writeStringToBuffer(font, "Hello, world!");
// and the buffer to the screen
writeBufferToScreen();
}
---
Should be fairly simple to follow, just realize that the image is
a 2d block for each char and that's why there's all those
multiplies and divides.
You can grab the font.png I used from here:
http://arsdnet.net/font.png
(it is the old IBM PC font)
And the dependencies to load that png are:
https://github.com/adamdruppe/arsd/blob/master/color.d
https://github.com/adamdruppe/arsd/blob/master/png.d
then pretty simple compile and run should get you the hello world.
More information about the Digitalmars-d-learn
mailing list