飴屋ぷろじぇくと

 ちょっとカテゴリを分けてみようかなっと。

--.--.--[--] スポンサーサイト

上記の広告は1ヶ月以上更新のないブログに表示されています。
新しい記事を書く事で広告が消せます。

2014.11.26[水] xlibでデスクトップに立つ。その3

まず、画像読み込みにバグがありました。で、それを修正。
XImageのバッファは色深度24bitの時はピクセルあたり32bitになるんですが、画像ファイルが1ピクセル24ビットのとき、バッファ側の32bit幅でコピーしていたため、未使用ビットに隣のデータがコピーされてしまって、これが悪さをしてマスクの生成が上手く行ってませんでした。現象としては画像のふちに乱発的に背景色のドットが発生します。
maru10x.png
よく見ないと判らないんですが………。
修正は以下。
/* BMPファイルを読みこんでXImageを返す */
XImage *load_bmp(Display *d, const char *filename, int *imwidth, int *imheight) {
char *bmpdata;
int scrn = DefaultScreen(d);
int depth = XDefaultDepth(d, 0);
Colormap cmap = DefaultColormap(d, scrn);
int width, height, bitcount, linelen, bpp;
XImage *img;
char *data;
XColor color;
int i, j, h, pixbytes;
bmpdata = loadbmpfile(filename, &width, &height, &bitcount, &linelen);
pixbytes = bitcount / 8;
bpp = depth >= 24 ? 4 : 2;
h = height;
if (height < 0) height = -height;
data = (char*)calloc(bpp, height * width);
for (i = 0; i < height; i++) {
int k = h < 0 ? i * linelen : (height - i -1) * linelen;
int m = i * width * bpp;
for (j = 0; j < width; j++) {
int r = k + j * pixbytes;
int s = m + j * bpp;
memcpy(data+s, bmpdata+r, pixbytes);
}
}
free(bmpdata);
img = XCreateImage( d, CopyFromParent, depth, ZPixmap,
0, data, width, height, bpp*8, bpp*width );
*imwidth = width;
*imheight = height;
return img;
}
さて。ではいきましょう。
11.ウィンドウに文字を描画するには
文字を表示するだけなら簡単です。こんな関数を使います。
XDrawString(display, win, gc, x, y, string, length)
これでイベントループのExposeイベントのところで描画してやります。
    } else if (event.xany.window == sub) {
if (event.xexpose.count == 0) {
XPutImage( dsp, sub, gc, image2, 0, 0, 0, 0, iwidth2, iheight2 );
XDrawString(dsp, sub, gc, 40, 50, str, strlen(str));
}
}
とりあえず文字列は固定で。
    const char str[] = "Debug information.";
maru11.png
簡単でした。でも何で英語? 
    const char str[] = "デバッグ情報〜";
maru11b.png

実はXDrawString()では、日本語などのマルチバイト文字列は表示出来ないんです。
12.日本語を表示するには
ポイントは三つ。
1.setlocale()でロケールを設定
2.フォントセットを生成
3.XmbDrawString()を使用する

いい加減ソースコードがごちゃごちゃして来たので1と2は関数にしました。
/* ロケールを設定します */
char *initLocale()
{
char *lc;
if ((lc = setlocale( LC_CTYPE, "")) == NULL ) {
printf("ロケールを設定できない\n");
} else if (!XSupportsLocale()) {
printf("現在のロケールをサポートしてない\n");
lc = NULL;
}
return lc;
}
/* フォントセットを作成します */
XFontSet getFontSet(Display *dsp, const char *namelist)
{
int missing_count;
char **missing_list;
char *def_string;
XFontSet fs = XCreateFontSet(dsp, namelist,
&missing_list, &missing_count, &def_string );

XFreeStringList(missing_list);
return fs;
}
そして、メイン関数では、
int main()
{
(…略…)

int drag = 0, rx = 0, cx = 0;
const char str[] = "デバッグ情報〜";
XFontSet fs;
/* ロケール */
if (initLocale() == NULL)
{
return 1;
}

/* ディスプレイ */
dsp = XOpenDisplay( NULL );
/* フォントセット */
fs = getFontSet(dsp, "-*-fixed-medium-r-normal--14-*-*-*");
if (fs == NULL) {
printf("フォントセット生成に失敗\n");
return 1;
}


(…略…)

/* アプリループ */
while (1) {
XEvent event;

(…略…)

} else if (event.xany.window == sub) {
if (event.xexpose.count == 0) {
XPutImage( dsp, sub, gc, image2, 0, 0, 0, 0, iwidth2, iheight2 );
XmbDrawString(dsp, sub, fs, gc, 40, 50, str, strlen(str));

(…以下略…)
これで日本語が表示できます。
あとは表示したい情報を文字列に入れて……
    int i;
char info[3][64];


(…略…)

sprintf(info[0], "width=%d", width);
sprintf(info[1], "height=%d", height);
sprintf(info[2], "depth=%d", DefaultDepth(dsp, screen));


(…略…)

} else if (event.xany.window == sub) {
if (event.xexpose.count == 0) {
XPutImage( dsp, sub, gc, image2, 0, 0, 0, 0, iwidth2, iheight2 );
XmbDrawString(dsp, sub, fs, gc, 40, 50, str, strlen(str));
for (i = 0; i < 3; i++) {
XmbDrawString(dsp, sub, fs, gc, 40, 70+i*20, info[i], strlen(info[i]));
}

}
}
maru12b.png
こんな感じに。

他にまだこんな話題もありますが、
13.もっと綺麗に表示するには(FreeTypeフォント)……Xftの使い方
14.ウィンドウを手前に表示など……XRaiseWindow()とか、二つのウィンドウの連携とか。

とりあえず、目標は達成したので今回はこれまで。
ここまでのソースコード

Comment






(編集・削除用)

Trackback

http://utau2009.blog114.fc2.com/tb.php/35-f677eb1d

この記事にトラックバック(FC2Blog User)

Copyright © 飴屋/菖蒲

上記広告は1ヶ月以上更新のないブログに表示されています。新しい記事を書くことで広告を消せます。