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.

Reply via email to