在 C 中实现字形模式

发布于 2024-09-11 20:34:19 字数 690 浏览 2 评论 0原文

我已在 Peter Van Der 的 专家 C 编程 中阅读了字形的实现林登。他描述了这种绘制字形图案的方法。这个问题严格限制在 C 编程的范围内。

static unsigned short stopwatch[] = {
    0x07C6,
    0x1FF7,
    0x383B,
    0x600C,
    0x600C,
    0xC006,
    0xC006,
    0xDF06,
    0xC106,
    0xC106,
    0x610C,
    0x610C,
    0x3838,
    0x1FF0,
    0x07C0,
    0x0000
};

然后定义

#define X )*2+1
#define _ )*2
#define s ((((((((((((((((0

绘制 16 位宽的字形。

然后上面的数组被转换为秒表的字形模式。

我们如何在不使用图形的情况下在屏幕上绘制这些字形?有没有什么方法可以绘制其他对象的字形图案,例如地图轮廓、人脸,而无需绘制每个像素,并且无需使用常规 C 图形?

是否遵循任何算法?

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?

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(2

别低头,皇冠会掉 2024-09-18 20:34:19

这是代码的更新,它在源代码中对秒表进行“Ascii Art”。查看历史记录,找到忠实于本书的版本。

#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]);
    }
}

注意:主要思想是您可以替换秒表数据中的原始十六进制数组,代码将生成与上面示例相同的数组。即,与宏结合使用时,十六进制数组和 ASCII ART 是等效的。

这对于链接到源的字体库最有帮助。即,与十六进制数组相比,此秒表数组在源中更容易可视化。

嗯...但是我们需要找出数组来实现任何其他对象的字形...还有其他方法来实现这个..?

我认为这是一个重要的观点,但我在任何地方都没有看到表达。二进制版本可以发送到位图硬件。然而,“ASCII ART”表示比十六进制数组更容易理解。另一种方法是使用二进制常量,尽管可视化效果不太好。

这是另一个问题您可能希望支持比灰度图像单个位更大的位深度。因此,您需要为每个“颜色深度”进行定义,然后对其进行编码。如果您正在编写一个将 SVG/BMP 等转换为“C”数组的程序,这将是创建输出的更好方法(以及传统的“机器生成内容”注释)。

您需要限制调色板以使其成为“有效 C”。 “C”中标识符的附加限制将字符空间限制为大小写字母、数字和下划线。例如, '。'期间是不允许的。 “W”和“R”是其他候选者(X 除外)。因此灰度图像的“调色板”可能是有限的。

我想我也看到它在一些 BDF 字体定义中使用。还有一篇关于空格编码标准的博客文章。空格对于编译器来说并不重要。然而,这对人类很重要。因此,虽然十六进制数组相当于机器,但它还是有帮助的。例如,随着时间的推移,应用程序可能有两个秒表字形,然后您想知道十六进制数组正在定义哪一个。


我最初的目标是找到一种好方法来实现编译器可以使用的“ASCII Art”。我采用了“Peter Van Der Linden”宏(可能源自 UseNet)并连接了一个半字节。这些不太可能导致名称冲突。它确实有一个缺点,即散布逗号,但我认为字形仍然可以识别,更紧凑,并且宏更容易理解。 [请参阅此帖子历史记录以了解使用原始宏的变体]。

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

怀中猫帐中妖 2024-09-18 20:34:19

只缺少几行代码:

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");
    }
}

瞧,秒表:

      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      

define 语句是获得该列表中的神奇值的简写:

$ 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

最后一个简介是一个表达式,它会导致某个值(在在本例中为 960 或 0x03c0),您可以在该“秒表”列表中使用。

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.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文