QQ登录

只需一步,快速开始

 找回密码
 注册

QQ登录

只需一步,快速开始

楼主: momotalo

欢迎访问“点阵中文”Wiki,为Linux制作中文字体

[复制链接]
发表于 2004-11-2 23:42:59 | 显示全部楼层
[quote:beac9c312e="shuyong"]处理这个问题很简单。就是有点烦:-(。

我们已知GB18030中文字的集合,用一个文本编辑软件cut掉不属于集合内的字就可以了。我是用vi做的,20分钟一个,有点累。

还有就是copy + paste,用xmbdfed,找X bdf:
6x12 iso10646 + 12 pixel
6x13 iso10646 + 13 pixel
7x14 iso10646 + 14 pixel
9x15 iso10646 + 15 pixel
8x16 iso10646 + 16 pixel
9x18 iso10646 + 18 pixel

一页一页地贴字,有点烦。而且15pixel的配对很难找。[/quote]
我觉得那些中文字体内嵌的点阵都是GB编码的,但是xmbdfed不认识,只能用iso10646的,所以才会这样
用fontforge和sbit32提出的点阵xmbdfed都无法打开
回复

使用道具 举报

 楼主| 发表于 2004-11-3 07:17:40 | 显示全部楼层
[quote:2c7cd4ce04="firefly"]唉!還是老老實實一點一點畫出來的字最實在。
從別人那兒提取的字,能拿到台面上嗎?
能夠大大方方的號稱是 GPL 的字型嗎?
恐怕自己都會覺得不好意思吧 :-([/quote]

firefly大侠在这里,向firefly的工作表示敬意!

我从你的New Sung中用我自己写的一个Qt程序提取出来了点阵,但好象有很多字的大小不一样。比如16X16px的字,出来的点阵有15X16,14X16等等,我现在不清楚是我的程序的问题,还是你制作点阵的时候专门这样设置的。

另外今天收到Arne Götje(leader of Unifonts project)的信,还没有来得及回,大家如果能够联合起来,分工合作,进展一定会更快!我可以把我的这个Wiki平台提供出来(比如建立映像),让一个社区参与点阵中文的制作,这样也不会再烦劳firefly大侠点坏另外一个鼠标了 (可惜,宣传不利,现在点阵中文Wiki的参与者与日递减 )
回复

使用道具 举报

 楼主| 发表于 2004-11-3 07:28:43 | 显示全部楼层
[quote:ffca045b17="shuyong"]这没有什么不好意思的。因为这是国家标准。既然是国家标准就存在公益的特性。既然是国家标准就要遵守(firefly是对岸的,有特殊情况,不在范围之内)。[/quote]

找来找去,好象也只有15X16点阵有国家标准(GB11458.1-89)
http://www.yyxx.sdu.edu.cn/content/faguibiaozhun/mingxibiao.htm

而且这个标准的点阵好象也没有找到什么地方可以免费获得。
回复

使用道具 举报

发表于 2004-11-3 10:04:37 | 显示全部楼层
[quote:2a7d0653cb="momotalo"][quote:2a7d0653cb="firefly"]唉!還是老老實實一點一點畫出來的字最實在。
從別人那兒提取的字,能拿到台面上嗎?
能夠大大方方的號稱是 GPL 的字型嗎?
恐怕自己都會覺得不好意思吧 :-([/quote]

firefly大侠在这里,向firefly的工作表示敬意!

我从你的New Sung中用我自己写的一个Qt程序提取出来了点阵,但好象有很多字的大小不一样。比如16X16px的字,出来的点阵有15X16,14X16等等,我现在不清楚是我的程序的问题,还是你制作点阵的时候专门这样设置的。

另外今天收到Arne Götje(leader of Unifonts project)的信,还没有来得及回,大家如果能够联合起来,分工合作,进展一定会更快!我可以把我的这个Wiki平台提供出来(比如建立映像),让一个社区参与点阵中文的制作,这样也不会再烦劳firefly大侠点坏另外一个鼠标了 (可惜,宣传不利,现在点阵中文Wiki的参与者与日递减 )[/quote]

提取的點陣大小不一,是因為 Bitmap 是以實際大小儲存在 truetype 中,在畫在畫布之前,還要計算出這個字符在畫布中的相對位置,請參考以下這段小弟實驗用的小程式,可以解出正確大小,稍微改寫,就能使用在您的程式之中:
[code:1]

// 程式名稱 : getbmp.cpp
// 作者 : Firefly([email protected])

#include <ft2build.h>
#include FT_FREETYPE_H
#include FT_GLYPH_H
#include FT_OUTLINE_H
#include FT_BBOX_H

#include <iostream>
#include <fstream>
#include <getopt.h>
#include <stdio.h>
#include <stdlib.h>

using namespace std;

static FT_Library library;
static FT_Face          face;

static unsigned int pix_size = 0;
static string font_name = "";
static string map_name = "";
static unsigned int char_code = 0;
static bool output_bdf = false;

static FT_Int32 load_flags = FT_LOAD_DEFAULT;
static FT_Int32 loadFlags = FT_LOAD_DEFAULT|FT_LOAD_IGNORE_GLOBAL_ADVANCE_WIDTH;

static void reset_scale( int  pointSize )
{
    (void)FT_Set_Pixel_Sizes( face, 0, pointSize);
}

int main(int argc, char **argv)
{
    static struct option long_opt[] =
    {
        {"size", 1, 0, 0},
        {"font", 1, 0, 0},
        {"char", 1, 0, 0},
        {"of", 1,  0, 0},
        {"ah", 0, 0, 0},
        {"nb", 0, 0, 0},
        {0, 0, 0, 0}
    };

    int opt_idx = 0, c = 0;

    while((c = getopt_long(argc, argv, "s:f:m:c:ab:",
        long_opt, &opt_idx)) != -1)
    {
        switch (c)
        {
            case 0:
                if (optarg) // 有參數
                {
                    if (long_opt[opt_idx].name == "size")
                        pix_size = atoi(optarg);
                    if (long_opt[opt_idx].name == "font")
                        font_name = optarg;
                    if (long_opt[opt_idx].name == "char")
                        char_code = atoi(optarg);
                    if (long_opt[opt_idx].name == "of")
                    {
                        if ((string)optarg == "bdf")
                        {
                            output_bdf = true;
                        }
                    }
                }
                else // 無參數
                {
                    if (long_opt[opt_idx].name == "ah")
                        loadFlags |= FT_LOAD_FORCE_AUTOHINT;
                    if (long_opt[opt_idx].name == "nb")
                        loadFlags |= FT_LOAD_NO_BITMAP;
                }
                break;
            case 's' : // size
                pix_size = atoi(optarg);
                break;
            case 'f' : // font
                font_name = optarg;
                break;
            case 'c' : // char code
                char_code = atoi(optarg);
                break;
        }
    }
#define FLOOR(x)    ((x) & -64)
#define CEIL(x)     (((x)+63) & -64)
#define TRUNC(x)    ((x) >> 6)
#define ROUND(x)    (((x)+32) & -64)

    // 初始化 Freetype 引擎
    if (FT_Init_FreeType(&library))
    {
        cerr << "Could not initialize FreeType library." << endl;
        exit(1);
    }

    if (FT_New_Face(library, (char *)font_name.c_str(), 0, &face))
    {
        cerr << "Could not open font.(" << font_name << ")" << endl;
        exit(1);
    }

    if (FT_Select_Charmap(face,ft_encoding_unicode))
    {
        cerr << "Not a unicode font." << endl;
        exit(1);
    }

    reset_scale(pix_size);
    int ascender = (face->ascender*pix_size + face->units_per_EM/2)/face->units_per_EM;
    int descender = pix_size - ascender;

    FT_ULong  charcode;
    FT_UInt   gindex;

    unsigned int count = 0;

    charcode = FT_Get_First_Char(face, &gindex);

    while (gindex)
    {
        if (FT_Load_Char(face, charcode, load_flags))
        {
            charcode = FT_Get_Next_Char(face, charcode, &gindex);
            continue;
        }
        FT_GlyphSlot slot = face->glyph;

        if (slot->format != ft_glyph_format_bitmap)
        {
            charcode = FT_Get_Next_Char(face, charcode, &gindex);
            continue;
        }

        count ++;

        int ymax = slot->bitmap_top - 1;
        int ymin = slot->bitmap_top - slot->bitmap.rows;
        int height = slot->bitmap.rows;
        if (slot->bitmap.rows == 0)
        {
            ymax = ymin;
            height = 1;
        }

        int xmin = slot->bitmap_left;
        int xmax = slot->bitmap_left + slot->bitmap.width - 1;
        int width = slot->bitmap.width;
        if (slot->bitmap.width == 0)
        {
            xmax = xmin;
            width = 1;
        }

        int true_width = TRUNC(slot->metrics.horiAdvance);
        int per_bytes_line = (true_width + 7 ) >> 3;
        int true_height = (height > pix_size) ? height : pix_size;
        int buf_size = per_bytes_line * true_height;
        unsigned char *bufBitmap = (unsigned char *) malloc (buf_size);
        memset (bufBitmap, 0, buf_size);

        int pitch = slot->bitmap.pitch ? slot->bitmap.pitch : 1;
        int size  = (ymax - ymin + 1) * pitch;
        unsigned char *buffer = (unsigned char *)malloc(size);

        memset(buffer, 0, size);
        if (slot->bitmap.rows && slot->bitmap.width)
            memcpy(buffer, slot->bitmap.buffer, size);

        int xoff = TRUNC(slot->metrics.horiBearingX);
        int yoff = TRUNC(slot->metrics.horiBearingY - slot->metrics.height);
        if (yoff < -(descender))
        {
            yoff = -(descender);
        }
        printf("Char code = 0x%X ( %d x %d )(Xoff:%d Yoff:%d) trueX:%d trueY:%d, ascender=%d, descender=%d\n", charcode, width, height, xoff, yoff, true_width, true_height, ascender, descender);
        int x, y;
        unsigned char *line = buffer;
        int top = ascender - yoff - height;
        if (top < 0)
        {
            top = 0;
        }
        unsigned char *dest = bufBitmap + (per_bytes_line * top);
        for (y=0 ; y < height; y++)
        {
            int bits = 7;
            for (x=0; x < width; x++)
            {
                int on = (line[x >>3] & 1 << bits);
                if (on)
                {
                    int offset = x + xoff;
                    int bitoffset = 7 - (offset % 8);
                    dest[offset >>3] |= 1 << bitoffset;
                }
                bits = bits ? bits -1 : 7;
            }
            line += pitch;
            dest += per_bytes_line;
        }

        line = bufBitmap;
        for (y=0 ; y < true_height; y++)
        {
            int bits = 7;
            for (x=0; x < true_width; x++)
            {
                cout << ((line[x >>3 ] & 1 << bits )? '*' : ' ');
                bits = bits ? bits -1 : 7;
            }
            cout << "| " << "[ " ;
            for (x=0; x <per_bytes_line ; x++)
            {
                printf("%02x", line[x]);
            }
            cout << " ]" << endl;
            line += per_bytes_line;
        }
        free(buffer);
        free(bufBitmap);
        charcode = FT_Get_Next_Char(face, charcode, &gindex);
    }

    cerr << "Total Characters = " << count << endl;
    return 0;
}
[/code:1]

[code:1]
編譯方法
g++ getbmp.cpp -o getbmp `freetype-config --cflags --libs`

執行
./getbmp -s [pixel_size] -f [字型檔案名稱]
[/code:1]
回复

使用道具 举报

 楼主| 发表于 2004-11-3 14:10:46 | 显示全部楼层
多谢firefly的回复和代码。看来里面需要计算offset和baseline之类的。
不过我用的Qt的例子中的一些代码,似乎应该也自动考虑了这些因素,
代码如下:

[code:1]    ....
   
    QPixmap pm(1,1);
    QFont    f( "AR PL New Sung", fsize );        // use New Sung
    QPainter p;
    QRect    r;                         // text bounding rectangle
    QPoint   bl;                        // text baseline position

    char a[3];
    char filename[100];
    int len;

    a[2]='\0';

    .... // (loop over i,j)

    a[0]=i+0xA0;
    a[1]=j+0xA0;

    str=QString(a);        // generate a character
    string = codec->toUnicode(str);  // conver it to GB2312
                                                // get position info
    p.begin( &pm );                     // first get the bounding
    p.setFont( f );                     //   text rectangle
    r = p.fontMetrics().boundingRect(string);
    bl = -r.topLeft();                  // get baseline position
    p.end();

    if(r.isNull()) continue;          // if empty, skip
                                           // if non-empty, draw it on pixmap canvas
    pm.resize( r.size() );              // resize to fit the text
    pm.fill( white );                   // fills pm with white
    p.begin( &pm );                     // begin painting pm
    p.setFont( f );                     // set the font
    p.setPen( blue );                   // set blue text color
    p.drawText( bl, string );           // draw the text
    p.end();                            // painting done
    ....
    pm.save(codec->toUnicode(filename),"PNG");
    ....
[/code:1]

但这样出来的仍然是大小不一致。所以我把这些导出的点阵都以左上角对齐了。
回复

使用道具 举报

发表于 2004-11-3 15:30:36 | 显示全部楼层
一般而言,點陣字都會留下一點空白,當做字與字、行與行的間隔。

以 16x16 大小的 Size 而言,實際可用的點字範圍是 15*15,當字型筆劃太少時,不一定會用到 15 * 15 有可能會變成 14 x 15 甚至 13 * 15,這是為了顧及整體外觀,否則筆劃簡單的字硬要畫滿 15x15,就會變得很胖 :-),您可以看看 simsun 的點陣字,也有不少這類的字。

但無論如何,這幾種大小的字,必須顯示在 16x16 當中,小弟的代碼中,有關 Xoffset 就是指這個字符最左邊的那一點與 16x16 最左邊的距離點數, 如果您導出的字一律與左上角對齊,最終顯示出來的話可能會出現字與字的間距不一的情況(英文尤其明顯)。

還有一點需注意的,就是點陣字符的(0,0)並不是從左上角開始,而是從左下角算起
請參考這裡:
http://freetype.sourceforge.net/freetype2/docs/tutorial/step2.html
還有這裡:
http://freetype.sourceforge.net/freetype2/docs/glyphs/glyphs-7.html
回复

使用道具 举报

发表于 2004-11-4 00:04:23 | 显示全部楼层
有心而无力啊,只能多做宣传工作了。。。
回复

使用道具 举报

发表于 2004-11-4 23:23:27 | 显示全部楼层
[quote:691a024965="shuyong"]这没有什么不好意思的。因为这是国家标准。既然是国家标准就存在公益的特性。既然是国家标准就要遵守(firefly是对岸的,有特殊情况,不在范围之内)。[/quote]
点阵字只有16x16的国标,更小的字体没有国标。我特意为这件事跑了一趟图书馆。下次准备再到中标局去翻翻。BTW,矢量字库也是有国家标准的,如果以后时间充裕了,我们甚至可以自己画一个黑体或者仿宋体的字库。

[quote:691a024965="shuyong"]具体地说,windows 2000/ windows XP里面带的simsun.ttc不符合标准。当时M$也相当强硬,明确说windows XP不打算支持GB18030。但后来又偷偷摸摸出了一个simsun18030.ttc。我估计是当时这个字体是赶不急了,出此下策。之所以说这么多,只是希望不走弯路,甚至可以走合理的捷径。[/quote]
微软没有再从中易手里买字体,那个18030的字体是方正的。
回复

使用道具 举报

发表于 2004-11-5 00:35:17 | 显示全部楼层
那用 16x16 的点阵字不存在版权问题?
有国家标准的字体?
回复

使用道具 举报

发表于 2004-11-5 14:45:52 | 显示全部楼层
[quote:428a25f167="mandrakechina"]
点阵字只有16x16的国标,更小的字体没有国标。我特意为这件事跑了一趟图书馆。下次准备再到中标局去翻翻。BTW,矢量字库也是有国家标准的,如果以后时间充裕了,我们甚至可以自己画一个黑体或者仿宋体的字库。
[/quote]

中标局在什么地方?对公众开放吗?

中国的事情有点怪。你在中标局可能找不到这方面的资料。这东西是由国家信息标准委员会(简称信标委)发布的。没有国家标准号,但有国家标准的效力。而且里面的字的集合比GB18030要多一些。我估计是由信标委具体执行和解释GB18030。估计因为出一个正式的国家标准时间太长,所以由委员会的形式发布方便一些。

[quote:428a25f167="mandrakechina"]

微软没有再从中易手里买字体,那个18030的字体是方正的。
[/quote]

有一句话说得好:魔鬼藏在细节里。
估计中易就是栽在这上面了。

因为汉字太复杂,12/13/14点阵太小,很多细节不能显示出来。这时候就需要简化显示。简化显示以前有几种方案。信标委标准的作用是定义是哪些合格的,其它是错别字。具体有多少我不记得了。现在还记得一个:
直线的"直",真实的"真",所有带"直"/"真"边旁的字,里面应该是三横。
在12点阵情况下,是很难画出三横的。
信标委要求是要么画出三横,要么简化为一竖。
东文的方案是画三横。
中易的方案是画两横,现在可以认为是错别字。

如此种种,不一而足。标准就是标准,没有多少道理可以讲。
回复

使用道具 举报

发表于 2004-11-10 01:11:03 | 显示全部楼层
看来还是有不少关心中文字体的高手,GPL的字体该有希望。
关于GPL的中文矢量字库,本人简单地写了一个思路,申请了一个项目http://gccf.cosoft.org.cn/,只是有心无力,关键是还没有时间真正地做这个事,为生活而奔波啊!希望有人能做完一个字体项目,百姓有福了。
回复

使用道具 举报

发表于 2004-11-10 01:38:59 | 显示全部楼层
不知道要多少人一起做才能作出一个这样的字体来……
回复

使用道具 举报

 楼主| 发表于 2004-11-10 09:52:29 | 显示全部楼层
=== 更新:2004/11/9 =

1. 导入GNU Unifont中的21003个16x16汉字点阵!其中GB2312部分的6763个汉字覆盖原有的从Firefly的字体中导出的点阵。

2. 字体编辑界面右侧参照的图片使用从Unifont生成的位图,完全消除版权隐患。

3. sitaphi服务器上的文件容量上限为500M,现已经使用了300M,为了减轻这个服务器的负荷,unifont的图片现由Dartmouth中国学生学者联谊会的服务器暂时存储(100M左右)。对于容量限制的问题,希望今后能找到解决办法。
回复

使用道具 举报

 楼主| 发表于 2004-11-14 13:46:34 | 显示全部楼层
=== 更新:2004/11/13 =

1. 感谢Tchaikov提供的javascript代码,现在您在编辑字体点阵时可以实时地查看真实大小的字体预览(位于下侧蓝框左端)!

2. 修正了字体编辑器一个bug,IE的用户现在也可以参与字体编辑。
回复

使用道具 举报

发表于 2004-11-21 14:34:17 | 显示全部楼层
[quote:6510cb9eb2="mandrakechina"]
微软没有再从中易手里买字体,那个18030的字体是方正的。[/quote]
按字体说明,应该还是中易的,只不过bitmap字体从方正中吸了不少,
simsun18030在sun jds(默认使用方正字体)中和方正宋体显示效果几乎一样()
回复

使用道具 举报

您需要登录后才可以回帖 登录 | 注册

本版积分规则

GMT+8, 2024-3-29 04:05 , Processed in 0.068165 second(s), 12 queries .

© 2021 Powered by Discuz! X3.5.

快速回复 返回顶部 返回列表