www.digitalmars.com         C & C++   DMDScript  

digitalmars.D.learn - Constructing text with astericks

reply aberba <karabutaworld gmail.com> writes:
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
next sibling parent Basile B. <b2.temp gmx.com> writes:
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
prev sibling next sibling parent reply Adam D. Ruppe <destructionator gmail.com> writes:
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 30 2018
parent reply aberba <karabutaworld gmail.com> writes:
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
parent reply Adam D. Ruppe <destructionator gmail.com> writes:
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
parent reply =?UTF-8?Q?Ali_=c3=87ehreli?= <acehreli yahoo.com> writes:
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
parent Patrick Schluter <Patrick.Schluter bbox.fr> writes:
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.
May 31 2018
prev sibling parent Kagamin <spam here.lot> writes:
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'
"*****",
"*    ",
"*****",
"    *",
"*****"],
...
];
Jun 01 2018