Thread overview
Constructing text with astericks
May 30, 2018
aberba
May 30, 2018
Basile B.
May 30, 2018
Adam D. Ruppe
May 31, 2018
aberba
May 31, 2018
Adam D. Ruppe
OT: Parsing object files for fun and profit
May 31, 2018
Ali Çehreli
May 31, 2018
Patrick Schluter
Jun 01, 2018
Kagamin
May 30, 2018
I've been given a challenge to write texts using asterisks to form the letters. D happen to have an unlimited amount of idioms yet i'm out out ideas as to the simplest approach. Task is to basically take a piece of text and write them as asterisks to the console.

*****  *
*      *
*****  *
    *  *
*****  *

First solution I found was to create a class for each letter...like new A(), new B() and implement the logic withing each class. This doesn't scale and i'll have to write about 24 or more classes.

Another complex but "makes sense" solution will be to use a GRID system like old digital watches but i'll need a more complex grid to draw complex letters using a dictionary of REPOPULATED indexes of asterisk for each word. First use the length of the string to compute the grid size and iterate over each character to indentify the dictionary of a letter's indexes to use:

*****
*******
**   **
*******
**  ***
**   ***  (an R using a more complex Grid)


How will you approach this problem in D idiomatically?
May 30, 2018
On Wednesday, 30 May 2018 at 22:57:06 UTC, aberba wrote:
> I've been given a challenge to write texts using asterisks to form the letters. D happen to have an unlimited amount of idioms yet i'm out out ideas as to the simplest approach. Task is to basically take a piece of text and write them as asterisks to the console.
>
> *****  *
> *      *
> *****  *
>     *  *
> *****  *
>
> First solution I found was to create a class for each letter...like new A(), new B() and implement the logic withing each class. This doesn't scale and i'll have to write about 24 or more classes.
>
> Another complex but "makes sense" solution will be to use a GRID system like old digital watches but i'll need a more complex grid to draw complex letters using a dictionary of REPOPULATED indexes of asterisk for each word. First use the length of the string to compute the grid size and iterate over each character to indentify the dictionary of a letter's indexes to use:
>
> *****
> *******
> **   **
> *******
> **  ***
> **   ***  (an R using a more complex Grid)
>
>
> How will you approach this problem in D idiomatically?

I'd use an ascii art approach:

- Programatically make bitmaps with each letter rendered using a monospaced font.
- use higher order functions to make 2d arrays of ' ' and '*'
May 30, 2018
On Wednesday, 30 May 2018 at 22:57:06 UTC, aberba wrote:
> How will you approach this problem in D idiomatically?

Well, I never bother with "idiomatically", so I can't speak to that, but a simple solution that would work is to realize that what you're basically asking for here is a bitmap.

Each letter in your "font" would be a little bitmap that you copy into a destination buffer - itself a larger bitmap.

Then, when it is complete, you can draw the destination buffer line by line to the screen.

The data for your font may just be a bunch of string arrays in source, or an actual bitmap file you create outside the program and load at runtime or something like that. Just remember that you can't just `buffer ~= letter` - you need to do line by line since the two bitmaps will have different sizes.
May 31, 2018
On Wednesday, 30 May 2018 at 23:11:06 UTC, Adam D. Ruppe wrote:
> On Wednesday, 30 May 2018 at 22:57:06 UTC, aberba wrote:
>> How will you approach this problem in D idiomatically?
>
> Well, I never bother with "idiomatically", so I can't speak to that, but a simple solution that would work is to realize that what you're basically asking for here is a bitmap.
>
> Each letter in your "font" would be a little bitmap that you copy into a destination buffer - itself a larger bitmap.
>
> Then, when it is complete, you can draw the destination buffer line by line to the screen.
>
> The data for your font may just be a bunch of string arrays in source, or an actual bitmap file you create outside the program and load at runtime or something like that. Just remember that you can't just `buffer ~= letter` - you need to do line by line since the two bitmaps will have different sizes.

That doesn't sound like a trivial thing to do. Ha ha
May 31, 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.
May 31, 2018
On 05/31/2018 09:49 AM, Adam D. Ruppe wrote:

> 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.

I remember doing similar things with fonts to add Turkish characters to Digital Research and Wordperfect products (around 1989-1992). Localizing by patching compiled code was fun. :)

My happiest accomplishment was localizing Ventura Publisher "cleanly" after realizing that their language-related "resource" file was just an object file compiled from a simple C source code which had just an array of strings in it:

char * texts[] = {
    "yes",
    "no",
    // ...
};

I parsed the object file to generate C source code, translated the C source code, and finally compiled it again. Voila! Ventura Publisher in Turkish, and everything lined-up perfectly. :) Before that, one had to patch the object file to abbreviate "evet" on top of "yes", "hayır" on top of "no", etc.

Ali

May 31, 2018
On Thursday, 31 May 2018 at 18:33:37 UTC, Ali Çehreli wrote:
> On 05/31/2018 09:49 AM, Adam D. Ruppe wrote:
>
> > 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.
>
> I remember doing similar things with fonts to add Turkish characters to Digital Research and Wordperfect products (around 1989-1992). Localizing by patching compiled code was fun. :)
>
> My happiest accomplishment was localizing Ventura Publisher "cleanly" after realizing that their language-related "resource" file was just an object file compiled from a simple C source code which had just an array of strings in it:
>
> char * texts[] = {
>     "yes",
>     "no",
>     // ...
> };
>
> I parsed the object file to generate C source code, translated the C source code, and finally compiled it again. Voila! Ventura Publisher in Turkish, and everything lined-up perfectly. :) Before that, one had to patch the object file to abbreviate "evet" on top of "yes", "hayır" on top of "no", etc.
>
> Ali

Look for bdf files. This is an quite old X-windows bitmap font file format that has the big advantage of being a simple text format. So it is easy to parse and transform. There are quite some fonts existing in that format.

https://en.wikipedia.org/wiki/Glyph_Bitmap_Distribution_Format

I had used it in an embedded project in the 90s and it was simple enough that a 80186 based terminal could handle bitmap proportional fonts without breaking a sweat.
June 01, 2018
I don't think bitmaps are a good idea, keep your font in text format with characters indexed by code unit:
immutable string[][] font=[
...
[ //'i'
"*",
"*",
"*",
"*",
"*"],
...
[ //'s'
"*****",
"*    ",
"*****",
"    *",
"*****"],
...
];