xcb无法显示freetype位图

huangapple go评论98阅读模式
英文:

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[] = {&quot;DejaVuSans&quot;};

    FT_Init_FreeType(&amp;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,&quot;could not load face&quot;);
    }

    FT_Load_Char(ft-&gt;face,&#39;a&#39;,FT_LOAD_RENDER|FT_LOAD_FORCE_AUTOHINT);
    FT_Bitmap ft_bitmap = ft-&gt;face-&gt;glyph-&gt;bitmap;

    logmsg(INFO,&quot;pitch = %i | rows = %i | width = %i&quot;,ft_bitmap.pitch,ft_bitmap.rows,ft_bitmap.width); /* pitch = 7 | rows = 7 | width = 7 */

    for (size_t i = 0; i &lt; ft_bitmap.rows*ft_bitmap.width; i++) {
        logmsg(INFO, &quot;value = %i | index = %i&quot;,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-&gt;root,screen.data-&gt;width_in_pixels,screen.data-&gt;height_in_pixels);
    if (xcb_request_check(c,cookie)) {
        logmsg(INFO,&quot;could not create pixmap&quot;);
    }

    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,&quot;could not create gc&quot;);
    }

    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,&quot;could not put image on pixmap | err %i | maj %i | min %i&quot;,error-&gt;error_code,error-&gt;major_code,error-&gt;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.)

huangapple
  • 本文由 发表于 2023年7月7日 04:14:36
  • 转载请务必保留本文链接:https://go.coder-hub.com/76632268.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定