かってきままな日々
2021-11-21 (Su) [長年日記]
_ 全角と半角の文字幅
固定幅フォントにおいては、2:1 になるのが正しいと思ってたんだけど…
なんでか、全角半角を混ぜてテキストで表を作ろうとすると、
必ず |
の位置が微妙にずれてしまう。
ここ数日ちょっと調べてみた。
freetype を直接ごりごり扱ってみたり。
#include <ft2build.h>
#include FT_FREETYPE_H
#include <freetype/ftimage.h>
static unsigned int text[] = {
0x00003042, 0x00003044, 0x00003046, 0x00003048,
0x0000304a, 0x0000304b, 0x0000304d, 0x0000304f,
0x00003051, 0x00003053, 0x00003055, 0x00003057,
0x00003059, 0x0000305b, 0x0000305d, 0x0000305f,
0x00003061, 0x00003064, 0x00003066, 0x00003068,
0x00003042, 0x00003044, 0x00003046, 0x00003048,
0x0000304a, 0x0000304b, 0x0000304d, 0x0000304f,
0x00003051, 0x00003053, 0x00003055, 0x00003057,
0x00003059, 0x0000305b, 0x0000305d, 0x0000305f,
0x00003061, 0x00003064, 0x00003066, 0x00003068,
0x0000000a,
0x00000061, 0x00000062, 0x00000063, 0x00000064,
0x00000065, 0x00000066, 0x00000067, 0x00000068,
0x00000069, 0x0000006a, 0x0000006b, 0x0000006c,
0x0000006d, 0x0000006e, 0x0000006f, 0x00000070,
0x00000071, 0x00000072, 0x00000073, 0x00000074,
0x00000075, 0x00000076, 0x00000077, 0x00000078,
0x00000079, 0x0000007a,
0x00000061, 0x00000062, 0x00000063, 0x00000064,
0x00000065, 0x00000066, 0x00000067, 0x00000068,
0x00000069, 0x0000006a, 0x0000006b, 0x0000006c,
0x0000006d, 0x0000006e, 0x0000006f, 0x00000070,
0x00000071, 0x00000072, 0x00000073, 0x00000074,
0x00000075, 0x00000076, 0x00000077, 0x00000078,
0x00000079, 0x0000007a,
0x0000000a,
};
#define LEN (sizeof text / sizeof text[0])
#define WIDTH 1024
#define HEIGHT 256
#define LEFT 16
#define TOP 128
static unsigned char paper[HEIGHT][WIDTH];
static void draw(FT_Bitmap *bitmap, int x, int y)
{
for (int j = 0; j < bitmap->rows; j++) {
for (int i = 0; i < bitmap->width; i++) {
unsigned char c = bitmap->buffer[j * bitmap->pitch + i];
if (c) {
if (y + j >= 0 && y + j < HEIGHT) {
if (x + i >= 0 && x + i < WIDTH)
paper[y + j][x + i] = 255;
}
}
}
}
}
int main(void)
{
FT_Library library;
int error;
error = FT_Init_FreeType(&library);
if (error) {
fprintf(stderr, "ft init error\n");
exit(1);
}
FT_Face face;
error = FT_New_Face(
library,
"/usr/share/fonts/TTF/NasuM-Regular-20141215.ttf",
0,
&face);
if (error) {
fprintf(stderr, "new face error\n");
exit(1);
}
error = FT_Set_Char_Size(
face,
0,
8 * 64,
300,
300);
if (error) {
fprintf(stderr, "set size error\n");
exit(1);
}
int x = LEFT, x6 = LEFT<<6, y = TOP;
unsigned int idces[LEN];
for (int i = 0; i < LEN; i++) {
if (text[i] == '\n') {
x = LEFT;
x6 = LEFT<<6;
y += 24;
continue;
}
idces[i] = FT_Get_Char_Index(face, text[i]);
error = FT_Load_Glyph(
face,
idces[i],
0 |
// FT_LOAD_DEFAULT | // x
FT_LOAD_NO_HINTING | // o
// FT_LOAD_PEDANTIC | // x
// FT_LOAD_NO_AUTOHINT | // x
0
);
if (error) {
fprintf(stderr, "no glyph error\n");
exit(1);
}
error = FT_Render_Glyph(
face->glyph,
FT_RENDER_MODE_NORMAL);
if (error) {
fprintf(stderr, "glyph render error\n");
exit(1);
}
draw(&face->glyph->bitmap,
(x6 >> 6) + face->glyph->bitmap_left,
y - face->glyph->bitmap_top);
x += face->glyph->advance.x >> 6;
x6 += face->glyph->advance.x;
}
printf("P3\n%d %d\n%d\n", WIDTH, HEIGHT, 255);
for (int y = 0; y < HEIGHT; y++) {
for (int x = 0; x < WIDTH; x++) {
if (paper[y][x]) {
printf("%d %d %d ", 255, 255, 255);
} else {
printf("%d %d %d ", 0, 0, 0);
}
printf("\n");
}
}
}
実行したら標準出力に ppm ファイルが出力されるので、適当にファイルにリダイレクトして 適当な画像ビューワで見る。
なんと、FT_LOAD_NO_HINTING を指定するとちゃんと 2:1 になるのね。 hinting が悪さしてる? でも fonts.conf で false にしても治らない。
うーーん…
emacs の FT_LOAD_xxx の箇所に全部 FT_LOAD_NO_HINTING を追加してみても、 やっぱりずれるし。
ゔ〜〜〜ん
freetype-infinality とかいうやつにしてみたけど変化なく。
もしや Ubuntu ならうまく設定してたりするのか? と思って Ubuntu live media で 起動してみたけど、やっぱりずれるし。
世の中、幅の比率はあまり気にしない方向なのか? テキストで表を作ろうってのがもう老害?
(3:2 のフォントもあるらしいけど、それは好みなので置いておく)
macOS 上の emacs だと問題ないんだけどな。その辺はさすが mac かな。