英文:
xcb unable to display freetype bitmap
问题
我正在尝试使用freetype来光栅化一个8位深度位图,并在xcb上呈现它在一个8位深度的像素图上。
一切都按照预期进行,直到我尝试调用xcb_put_image_checked()函数。该函数返回一个错误代码16(Length),一个主要代码72(PutImage)和一个次要代码0。根据我的了解,这个错误意味着我传递给函数的位图缓冲区的长度不正确。经过大量测试,我逐字节打印了缓冲区并手动将数据转换为位图,位图的大小与我指定给函数的大小一致。位图中没有任何可能改变大小的填充,因为位图的pitch = 7,rows = 7,width = 7。像素图和位图的深度匹配。我对xcb_put_image_checked()为何失败感到困惑。我还尝试了(ft_bitmap.width*ft_bitmap.rows)-1作为大小。
这是生成错误的我的代码(抱歉它有些杂乱):
void testing() {
FT_Library library;
char *fonts[] = {"DejaVuSans"};
FT_Init_FreeType(&library);
/* custom function that loads faces from font config patterns proven to work in this instance */
xcb_drw_face_t *ft = xcb_drw_faces_load(library, fonts, 1);
if (!ft) {
logmsg(INFO, "could not load face");
}
FT_Load_Char(ft->face, 'a', FT_LOAD_RENDER | FT_LOAD_FORCE_AUTOHINT);
FT_Bitmap ft_bitmap = ft->face->glyph->bitmap;
logmsg(INFO, "pitch = %i | rows = %i | width = %i", ft_bitmap.pitch, ft_bitmap.rows, ft_bitmap.width); /* pitch = 7 | rows = 7 | width = 7 */
for (size_t i = 0; i < ft_bitmap.rows * ft_bitmap.width; i++) {
logmsg(INFO, "value = %i | index = %i", ft_bitmap.buffer[i], i);
}
xcb_void_cookie_t cookie;
xcb_generic_error_t *error;
xcb_pixmap_t pixmap = xcb_generate_id(c);
cookie = xcb_create_pixmap_checked(c, 8, pixmap, screen.data->root, screen.data->width_in_pixels, screen.data->height_in_pixels);
if (xcb_request_check(c, cookie)) {
logmsg(INFO, "could not create pixmap");
}
xcb_gcontext_t gc = xcb_generate_id(c);
cookie = xcb_create_gc_checked(c, gc, pixmap, 0, 0);
if (xcb_request_check(c, cookie)) {
logmsg(INFO, "could not create gc");
}
cookie = xcb_put_image_checked(c, XCB_IMAGE_FORMAT_Z_PIXMAP, pixmap, gc, ft_bitmap.width, ft_bitmap.rows, 0, 0, 0, 8, ft_bitmap.width * ft_bitmap.rows, ft_bitmap.buffer);
if ((error = xcb_request_check(c, cookie))) {
logmsg(INFO, "could not put image on pixmap | err %i | maj %i | min %i", error->error_code, error->major_code, error->minor_code);
}
xcb_drw_faces_free(ft);
xcb_free_pixmap(c, pixmap);
xcb_free_gc(c, gc);
FT_Done_FreeType(library);
return;
}
这是我手动转换的图像 - 在这里输入图像描述
英文:
I am trying to use freetype to rasterize a 8-bit depth bitmap and render it on a 8-bit depth pixmap in xcb.
Everything works as accordingly until I try to call xcb_put_image_checked(). The function returns an error code of 16 (Length), a major code of 72 (PutImage) and a minor code of 0. From what I have gathered the error means the length of the bitmap buffer I am passing to the function is incorrect. After lots of testing I have printed the buffer out byte for byte and manually converted the data to a bitmap and the bitmap comes out correct with the size I have specified to the function. There is no padding in the bitmap that could change the size as bitmap.pitch = 7, bitmap.rows = 7, and bitmap.width = 7. The depth of the pixmap and bitmap match. I am confused as to why xcb_put_image_checked() fails. I have also tried (ft_bitmap.width*ft_bitmap.rows)-1 for the size too.
Here is my code that generates the error (sorry its sloppy)
void testing() {
FT_Library library;
char *fonts[] = {"DejaVuSans"};
FT_Init_FreeType(&library);
/* custom function that loads faces from font config patterns proven to work in this instance */
xcb_drw_face_t *ft = xcb_drw_faces_load(library,fonts,1);
if (!ft) {
logmsg(INFO,"could not load face");
}
FT_Load_Char(ft->face,'a',FT_LOAD_RENDER|FT_LOAD_FORCE_AUTOHINT);
FT_Bitmap ft_bitmap = ft->face->glyph->bitmap;
logmsg(INFO,"pitch = %i | rows = %i | width = %i",ft_bitmap.pitch,ft_bitmap.rows,ft_bitmap.width); /* pitch = 7 | rows = 7 | width = 7 */
for (size_t i = 0; i < ft_bitmap.rows*ft_bitmap.width; i++) {
logmsg(INFO, "value = %i | index = %i",ft_bitmap.buffer[i],i);
}
xcb_void_cookie_t cookie;
xcb_generic_error_t *error;
xcb_pixmap_t pixmap = xcb_generate_id(c);
cookie = xcb_create_pixmap_checked(c,8,pixmap,screen.data->root,screen.data->width_in_pixels,screen.data->height_in_pixels);
if (xcb_request_check(c,cookie)) {
logmsg(INFO,"could not create pixmap");
}
xcb_gcontext_t gc = xcb_generate_id(c);
cookie = xcb_create_gc_checked(c,gc,pixmap,0,0);
if (xcb_request_check(c,cookie)) {
logmsg(INFO,"could not create gc");
}
cookie = xcb_put_image_checked(c,XCB_IMAGE_FORMAT_Z_PIXMAP,pixmap,gc,ft_bitmap.width,ft_bitmap.rows,0,0,0,8,ft_bitmap.width*ft_bitmap.rows,ft_bitmap.buffer);
if ((error = xcb_request_check(c,cookie))) {
logmsg(INFO,"could not put image on pixmap | err %i | maj %i | min %i",error->error_code,error->major_code,error->minor_code);
}
xcb_drw_faces_free(ft);
xcb_free_pixmap(c,pixmap);
xcb_free_gc(c,gc);
FT_Done_FreeType(library);
return;
}
Here is the image I manually converted - enter image description here
答案1
得分: 0
这是来自您的X11服务器要求的。以下是xdpyinfo
输出的一部分:
支持的像素图格式:
深度 1,每像素位数 1,扫描线填充 32
深度 4,每像素位数 8,扫描线填充 32
深度 8,每像素位数 8,扫描线填充 32
深度 15,每像素位数 16,扫描线填充 32
深度 16,每像素位数 16,扫描线填充 32
深度 24,每像素位数 32,扫描线填充 32
深度 32,每像素位数 32,扫描线填充 32
这里的scanline_pad
为32,即您看到的四个字节的填充。
这在https://www.x.org/releases/X11R7.6/doc/xproto/x11protocol.html#id2625443 中有一些解释:
每个扫描线都填充到位图扫描线填充所指定的位数的倍数。填充位的值是任意的。扫描线按位图扫描线单位指定的位数的倍数进行量化。位图扫描线单位始终小于或等于位图扫描线填充。在...
(老实说,我认为我从未见过一个不需要将填充对齐到四个字节倍数的X11服务器。)
英文:
This comes from a requirement from your X11 server. Here is a snippet of output from xdpyinfo
:
supported pixmap formats:
depth 1, bits_per_pixel 1, scanline_pad 32
depth 4, bits_per_pixel 8, scanline_pad 32
depth 8, bits_per_pixel 8, scanline_pad 32
depth 15, bits_per_pixel 16, scanline_pad 32
depth 16, bits_per_pixel 16, scanline_pad 32
depth 24, bits_per_pixel 32, scanline_pad 32
depth 32, bits_per_pixel 32, scanline_pad 32
The scanline_pad
of 32 here is the four bytes of padding you are seeing.
This is (a bit) explained in https://www.x.org/releases/X11R7.6/doc/xproto/x11protocol.html#id2625443:
> Each scanline is padded to a multiple of bits as given by bitmap-scanline-pad. The pad bits are of arbitrary value. The scanline is quantized in multiples of bits as given by bitmap-scanline-unit. The bitmap-scanline-unit is always less than or equal to the bitmap-scanline-pad. Within
(To be honest, I think I never saw an X11 server not requiring a padding to a multiple of four bytes.)
通过集体智慧和协作来改善编程学习和解决问题的方式。致力于成为全球开发者共同参与的知识库,让每个人都能够通过互相帮助和分享经验来进步。
评论