Reputation: 3021
I have read this implementation of glyphs in the Expert C Programming by Peter Van Der Linden. He states this method to draw a glyph pattern. This question is strictly restricted to the context of C programming.
static unsigned short stopwatch[] = {
0x07C6,
0x1FF7,
0x383B,
0x600C,
0x600C,
0xC006,
0xC006,
0xDF06,
0xC106,
0xC106,
0x610C,
0x610C,
0x3838,
0x1FF0,
0x07C0,
0x0000
};
and then define
#define X )*2+1
#define _ )*2
#define s ((((((((((((((((0
for drawing glyphs 16-bits wide.
Then the above array is converted to a glyph pattern of a StopWatch.
How do we draw those glyphs on the screen without using the graphics? Is there any method to draw the glyph patterns of other objects like outline of maps, face of a person roughly without having to plot each of the pixels, and without using the regular C graphics?
Are there any algorithms that were followed?
Upvotes: 3
Views: 787
Reputation: 22460
Here is an update of the code which does an 'Ascii Art' of the stopwatch in source. See history for versions that are faithful to the book.
#include <stdio.h>
#define ____ 0
#define ___X 1
#define __X_ 2
#define __XX 3
#define _X__ 4
#define _X_X 5
#define _XX_ 6
#define _XXX 7
#define X___ 8
#define X__X 9
#define X_X_ 10
#define X_XX 11
#define XX__ 12
#define XX_X 13
#define XXX_ 14
#define XXXX 15
#define D16(A,B,C,D) ((A)<<12|(B<<8)|(C<<4)|D)
#define ALEN(A) (sizeof(A)/sizeof(A[0]))
static unsigned short stopwatch[] = {
D16(____,_XXX,XX__,_XX_), // 0x07c6
D16(___X,XXXX,XXXX,_XXX), // 0x1ff7
D16(__XX,X___,__XX,X_XX), // 0x383b
D16(_XX_,____,____,XX__), // 0x600c
D16(_XX_,____,____,XX__), // 0x600c
D16(XX__,____,____,_XX_), // 0xc006
D16(XX__,____,____,_XX_), // 0xc006
D16(XX_X,XXXX,____,_XX_), // 0xdf06
D16(XX__,___X,____,_XX_), // 0xc106
D16(XX__,___X,____,_XX_), // 0xc106
D16(_XX_,___X,____,XX__), // 0x610c
D16(_XX_,___X,____,XX__), // 0x610c
D16(__XX,X___,__XX,X___), // 0x3838
D16(___X,XXXX,XXXX,____), // 0x1ff0
D16(____,_XXX,XX__,____), // 0x07c0
};
int main(void)
{
unsigned int i, idx;
const char *pattern[] = {
"____", /* 0 */ "___X", /* 1 */ "__X_", /* 2 */ "__XX", /* 3 */
"_X__", /* 4 */ "_X_X", /* 5 */ "_XX_", /* 6 */ "_XXX", /* 7 */
"X___", /* 8 */ "X__X", /* 9 */ "X_X_", /* 10 */ "X_XX", /* 11 */
"XX__", /* 12 */ "XX_X", /* 13 */ "XXX_", /* 14 */ "XXXX" /* 15 */
};
for (i = 0; i < ALEN(stopwatch); i++)
{
printf("D16(");
idx = (stopwatch[i] >> 12) & 0xf;
printf("%s,", pattern[idx]);
idx = (stopwatch[i] >> 8) & 0xf;
printf("%s,", pattern[idx]);
idx = (stopwatch[i] >> 4) & 0xf;
printf("%s,", pattern[idx]);
idx = (stopwatch[i]) & 0xf;
printf("%s), // 0x%04x\n", pattern[idx], stopwatch[i]);
}
}
NB: The main idea is that you can substitute the original hex array in stopwatch data and the code will generate the same array as the sample above. Ie, the hex array and the ASCII ART are equivalent when combined with the macros.
This is most helpful in font libraries that are linked into source. Ie, this stopwatch array is much easier to visualize in the source versus the hex array.
Hmm...But we need to find out the array to implement any other object's glyph ...Are there any other ways to implement this .. ?
I think this is an important point that I did not see expressed anywhere. The binary version can be sent to bitmapped hardware. However, the 'ASCII ART' representation is much easier to comprehend than a hex array. Another way to do this is with binary constants, although the visualization is not as good.
Here is another question where you might want to support a bit depth larger than a single bit for grey scale images. So, you need to make a define for each 'colour depth' and then encode that. If you are writing a program that translates SVG/BMP, etc to a 'C' array this would be a better way to create the output (as well as a traditional "MACHINE GENERATE CONTENT" comment).
You need to limit the palette to make it 'valid C'. The additional restriction of an identifier in 'C' limits the character space to upper and lower letter, numbers and the underbar. For instance, '.' period is not allowed. 'W' and 'R' are other candidates (besides X). So the 'palette' for grey scale images maybe limited.
I think I also saw this used in some BDF font definitions. There was also a blog post on coding standards in regards to whitespace. The whitespace does not matter to a compiler. However, it matters to a human. So while the hex array is equivalent to the machine, it is helpful. For instance, over time, the application might have two stopwatch glyphs and then you wonder which one the hex array is defining.
My original goal was to find a good way to implement the 'ASCII Art' that is consumable by a compiler. I took 'Peter Van Der Linden' macros (which may originate from UseNet) and concatenated an nibble. These are much less likely to cause name conflicts. It does have a downside of having commas interspersed, but I think the glyph is still recognizable, a little more compact and the macros are much easier to understand. [See this posts history for a variant using the original macros].
Upvotes: 2
Reputation: 47114
There is just a few lines of code missing:
int main()
{
int i,j;
for ( i=0;stopwatch[i];i++ )
{
for ( j=1<<16;j;j>>=1 ) printf("%c",stopwatch[i]&j?'o':' ');
printf("\n");
}
}
voila, stopwatch:
ooooo oo
ooooooooo ooo
ooo ooo oo
oo oo
oo oo
oo oo
oo oo
oo ooooo oo
oo o oo
oo o oo
oo o oo
oo o oo
ooo ooo
ooooooooo
ooooo
The define
statements are a shorthand to arrive at the magic values in that list:
$ gcc -E -x c -
#define X )*2+1
#define _ )*2
#define s ((((((((((((((((0
s _ _ _ _ _ _ X X X X _ _ _ _ _ _
// will be preprocessed to:
^D
((((((((((((((((0 )*2 )*2 )*2 )*2 )*2 )*2 )*2+1 )*2+1 )*2+1 )*2+1 )*2 )*2 )*2 )*2 )*2 )*2
That last blurb is an expression which leads to some value (in this case 960 or 0x03c0) you could use in that "stopwatch" list.
Upvotes: 1