cnhnln
发表于 2004-11-2 23:42:59
处理这个问题很简单。就是有点烦:-(。
我们已知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的配对很难找。
我觉得那些中文字体内嵌的点阵都是GB编码的,但是xmbdfed不认识,只能用iso10646的,所以才会这样
用fontforge和sbit32提出的点阵xmbdfed都无法打开
momotalo
发表于 2004-11-3 07:17:40
唉!還是老老實實一點一點畫出來的字最實在。
從別人那兒提取的字,能拿到台面上嗎?
能夠大大方方的號稱是 GPL 的字型嗎?
恐怕自己都會覺得不好意思吧 :-(
firefly大侠在这里,向firefly的工作表示敬意!
我从你的New Sung中用我自己写的一个Qt程序提取出来了点阵,但好象有很多字的大小不一样。比如16X16px的字,出来的点阵有15X16,14X16等等,我现在不清楚是我的程序的问题,还是你制作点阵的时候专门这样设置的。
另外今天收到Arne Götje(leader of Unifonts project)的信,还没有来得及回,大家如果能够联合起来,分工合作,进展一定会更快!我可以把我的这个Wiki平台提供出来(比如建立映像),让一个社区参与点阵中文的制作,这样也不会再烦劳firefly大侠点坏另外一个鼠标了:) (可惜,宣传不利,现在点阵中文Wiki的参与者与日递减 :( )
momotalo
发表于 2004-11-3 07:28:43
这没有什么不好意思的。因为这是国家标准。既然是国家标准就存在公益的特性。既然是国家标准就要遵守(firefly是对岸的,有特殊情况,不在范围之内)。
找来找去,好象也只有15X16点阵有国家标准(GB11458.1-89)
http://www.yyxx.sdu.edu.cn/content/faguibiaozhun/mingxibiao.htm
而且这个标准的点阵好象也没有找到什么地方可以免费获得。
firefly
发表于 2004-11-3 10:04:37
唉!還是老老實實一點一點畫出來的字最實在。
從別人那兒提取的字,能拿到台面上嗎?
能夠大大方方的號稱是 GPL 的字型嗎?
恐怕自己都會覺得不好意思吧 :-(
firefly大侠在这里,向firefly的工作表示敬意!
我从你的New Sung中用我自己写的一个Qt程序提取出来了点阵,但好象有很多字的大小不一样。比如16X16px的字,出来的点阵有15X16,14X16等等,我现在不清楚是我的程序的问题,还是你制作点阵的时候专门这样设置的。
另外今天收到Arne Götje(leader of Unifonts project)的信,还没有来得及回,大家如果能够联合起来,分工合作,进展一定会更快!我可以把我的这个Wiki平台提供出来(比如建立映像),让一个社区参与点阵中文的制作,这样也不会再烦劳firefly大侠点坏另外一个鼠标了:) (可惜,宣传不利,现在点阵中文Wiki的参与者与日递减 :( )
提取的點陣大小不一,是因為 Bitmap 是以實際大小儲存在 truetype 中,在畫在畫布之前,還要計算出這個字符在畫布中的相對位置,請參考以下這段小弟實驗用的小程式,可以解出正確大小,稍微改寫,就能使用在您的程式之中:
// 程式名稱 : 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( intpointSize )
{
(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_ULongcharcode;
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;
}
編譯方法
g++ getbmp.cpp -o getbmp `freetype-config --cflags --libs`
執行
./getbmp -s [pixel_size] -f [字型檔案名稱]
momotalo
发表于 2004-11-3 14:10:46
多谢firefly的回复和代码。看来里面需要计算offset和baseline之类的。
不过我用的Qt的例子中的一些代码,似乎应该也自动考虑了这些因素,
代码如下:
....
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");
....
但这样出来的仍然是大小不一致。所以我把这些导出的点阵都以左上角对齐了。
firefly
发表于 2004-11-3 15:30:36
一般而言,點陣字都會留下一點空白,當做字與字、行與行的間隔。
以 16x16 大小的 Size 而言,實際可用的點字範圍是 15*15,當字型筆劃太少時,不一定會用到 15 * 15 有可能會變成 14 x 15 甚至 13 * 15,這是為了顧及整體外觀,否則筆劃簡單的字硬要畫滿 15x15,就會變得很胖 :-),您可以看看 simsun 的點陣字,也有不少這類的字。
但無論如何,這幾種大小的字,必須顯示在 16x16 當中,小弟的代碼中,有關 Xoffset 就是指這個字符最左邊的那一點與 16x16 最左邊的距離點數, 如果您導出的字一律與左上角對齊,最終顯示出來的話可能會出現字與字的間距不一的情況(英文尤其明顯)。
還有一點需注意的,就是點陣字符的(0,0)並不是從左上角開始,而是從左下角算起 :mrgreen:
請參考這裡:
http://freetype.sourceforge.net/freetype2/docs/tutorial/step2.html
還有這裡:
http://freetype.sourceforge.net/freetype2/docs/glyphs/glyphs-7.html
schoolwind
发表于 2004-11-4 00:04:23
有心而无力啊,只能多做宣传工作了。。。
mandrakechina
发表于 2004-11-4 23:23:27
这没有什么不好意思的。因为这是国家标准。既然是国家标准就存在公益的特性。既然是国家标准就要遵守(firefly是对岸的,有特殊情况,不在范围之内)。
点阵字只有16x16的国标,更小的字体没有国标。我特意为这件事跑了一趟图书馆。下次准备再到中标局去翻翻。BTW,矢量字库也是有国家标准的,如果以后时间充裕了,我们甚至可以自己画一个黑体或者仿宋体的字库。
具体地说,windows 2000/ windows XP里面带的simsun.ttc不符合标准。当时M$也相当强硬,明确说windows XP不打算支持GB18030。但后来又偷偷摸摸出了一个simsun18030.ttc。我估计是当时这个字体是赶不急了,出此下策。之所以说这么多,只是希望不走弯路,甚至可以走合理的捷径。
微软没有再从中易手里买字体,那个18030的字体是方正的。
Gavin_tju
发表于 2004-11-5 00:35:17
那用 16x16 的点阵字不存在版权问题?
有国家标准的字体?
shuyong
发表于 2004-11-5 14:45:52
点阵字只有16x16的国标,更小的字体没有国标。我特意为这件事跑了一趟图书馆。下次准备再到中标局去翻翻。BTW,矢量字库也是有国家标准的,如果以后时间充裕了,我们甚至可以自己画一个黑体或者仿宋体的字库。
中标局在什么地方?对公众开放吗?
中国的事情有点怪。你在中标局可能找不到这方面的资料。这东西是由国家信息标准委员会(简称信标委)发布的。没有国家标准号,但有国家标准的效力。而且里面的字的集合比GB18030要多一些。我估计是由信标委具体执行和解释GB18030。估计因为出一个正式的国家标准时间太长,所以由委员会的形式发布方便一些。
微软没有再从中易手里买字体,那个18030的字体是方正的。
有一句话说得好:魔鬼藏在细节里。
估计中易就是栽在这上面了。
因为汉字太复杂,12/13/14点阵太小,很多细节不能显示出来。这时候就需要简化显示。简化显示以前有几种方案。信标委标准的作用是定义是哪些合格的,其它是错别字。具体有多少我不记得了。现在还记得一个:
直线的"直",真实的"真",所有带"直"/"真"边旁的字,里面应该是三横。
在12点阵情况下,是很难画出三横的。
信标委要求是要么画出三横,要么简化为一竖。
东文的方案是画三横。
中易的方案是画两横,现在可以认为是错别字。
如此种种,不一而足。标准就是标准,没有多少道理可以讲。
waq
发表于 2004-11-10 01:11:03
看来还是有不少关心中文字体的高手,GPL的字体该有希望。
关于GPL的中文矢量字库,本人简单地写了一个思路,申请了一个项目http://gccf.cosoft.org.cn/,只是有心无力,关键是还没有时间真正地做这个事,为生活而奔波啊!希望有人能做完一个字体项目,百姓有福了。
cobranail
发表于 2004-11-10 01:38:59
不知道要多少人一起做才能作出一个这样的字体来……
momotalo
发表于 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左右)。对于容量限制的问题,希望今后能找到解决办法。
momotalo
发表于 2004-11-14 13:46:34
=== 更新:2004/11/13 =
1. 感谢Tchaikov提供的javascript代码,现在您在编辑字体点阵时可以实时地查看真实大小的字体预览(位于下侧蓝框左端)!
2. 修正了字体编辑器一个bug,IE的用户现在也可以参与字体编辑。
hantsy
发表于 2004-11-21 14:34:17
微软没有再从中易手里买字体,那个18030的字体是方正的。
按字体说明,应该还是中易的,只不过bitmap字体从方正中吸了不少,
simsun18030在sun jds(默认使用方正字体)中和方正宋体显示效果几乎一样()