【问题标题】:Rendering asian characters using Cairo in C++?在 C++ 中使用 Cairo 渲染亚洲字符?
【发布时间】:2016-03-31 16:31:27
【问题描述】:

我正在尝试编写一个以 UTF-8 呈现亚洲字符的程序。当我尝试在终端或文本编辑器环境中呈现字符时,它会正确呈现。当我尝试在 cairo 中渲染时,我的输出中呈现了矩形(不是我期望的 UTF8 字符)。

下面是我正在运行的示例代码,它生成带有渲染文本的 PNG 文件输出。当我在 gcc 中编译并运行代码时,我没有得到预期的字符 と,而是得到一个矩形。我目前正在运行来自http://cairographics.org/tutorial/ 的示例,并为其提供我想要渲染的特殊字符。

#include <math.h>
#include <stdio.h>
#include <cairo.h>

int
main (int argc, char *argv[])
{
//CODE FROM http://cairographics.org/tutorial/textextents.c
    /* Variable declarations */
    cairo_surface_t *surface;
    cairo_t *cr;
    double x, y, px, ux=1, uy=1, dashlength;
    char text[]= u8"と";
    cairo_font_extents_t fe;
    cairo_text_extents_t te;

    /* Prepare drawing area */
    surface = cairo_image_surface_create (CAIRO_FORMAT_ARGB32, 240, 240);
    cr = cairo_create (surface);
    /* Example is in 26.0 x 1.0 coordinate space */
    cairo_scale (cr, 240, 240);
    cairo_set_font_size (cr, 0.5);

    /* Drawing code goes here */
    cairo_set_source_rgb (cr, 0.0, 0.0, 0.0);
    cairo_select_font_face (cr, "Sans",
            CAIRO_FONT_SLANT_NORMAL, CAIRO_FONT_WEIGHT_BOLD);
    cairo_font_extents (cr, &fe);

    cairo_device_to_user_distance (cr, &ux, &uy);
    if (ux > uy)
        px = ux;
    else
        px = uy;
    cairo_font_extents (cr, &fe);
    cairo_text_extents (cr, text, &te);
    x = 0.5 - te.x_bearing - te.width / 2;
    y = 0.5 - fe.descent + fe.height / 2;

    /* baseline, descent, ascent, height */
    cairo_set_line_width (cr, 4*px);
    dashlength = 9*px;
    cairo_set_dash (cr, &dashlength, 1, 0);
    cairo_set_source_rgba (cr, 0, 0.6, 0, 0.5);
    cairo_move_to (cr, x + te.x_bearing, y);
    cairo_rel_line_to (cr, te.width, 0);
    cairo_move_to (cr, x + te.x_bearing, y + fe.descent);
    cairo_rel_line_to (cr, te.width, 0);
    cairo_move_to (cr, x + te.x_bearing, y - fe.ascent);
    cairo_rel_line_to (cr, te.width, 0);
    cairo_move_to (cr, x + te.x_bearing, y - fe.height);
    cairo_rel_line_to (cr, te.width, 0);
    cairo_stroke (cr);

    /* extents: width & height */
    cairo_set_source_rgba (cr, 0, 0, 0.75, 0.5);
    cairo_set_line_width (cr, px);
    dashlength = 3*px;
    cairo_set_dash (cr, &dashlength, 1, 0);
    cairo_rectangle (cr, x + te.x_bearing, y + te.y_bearing, te.width, te.height);
    cairo_stroke (cr);

    /* text */
    cairo_move_to (cr, x, y);
    cairo_set_source_rgb (cr, 0, 0, 0);
    cairo_show_text (cr, text);

    /* bearing */
    cairo_set_dash (cr, NULL, 0, 0);
    cairo_set_line_width (cr, 2 * px);
    cairo_set_source_rgba (cr, 0, 0, 0.75, 0.5);
    cairo_move_to (cr, x, y);
    cairo_rel_line_to (cr, te.x_bearing, te.y_bearing);
    cairo_stroke (cr);

    /* text's advance */
    cairo_set_source_rgba (cr, 0, 0, 0.75, 0.5);
    cairo_arc (cr, x + te.x_advance, y + te.y_advance, 5 * px, 0, 2 * M_PI);
    cairo_fill (cr);

    /* reference point */
    cairo_arc (cr, x, y, 5 * px, 0, 2 * M_PI);
    cairo_set_source_rgba (cr, 0.75, 0, 0, 0.5);
    cairo_fill (cr);

    /* Write output and clean up */
    cairo_surface_write_to_png (surface, "textextents.png");
    cairo_destroy (cr);
    cairo_surface_destroy (surface);

    return 0;
}

我意识到 C++ 中的字符只有 8 位,不能期望扩展到我尝试渲染的特殊字符集,所以要让它工作,我需要以不同的方式表示特殊字符吗?

这是我运行代码时得到的图像:

那么如何在 Cairo 中渲染特殊字符呢?我需要改用 Pango,还是我在 C++ 中的表示根本不正确?

“a”和“á”等普通字符正确呈现

我已经设法让一些字符使用 Pango 在 GtkDrawingArea 小部件上呈现,所以这似乎是 Cairo 的问题。

【问题讨论】:

  • 这是 C 代码的直接链接。我正在更新它以显示网站
  • 您是否安装了正确的字体?
  • 在终端、firefox 和我的所有其他应用程序中呈现
  • 你的 C++ 是正确的,只要你能渲染其他字符。尝试以u8"a" 开头。
  • 您使用的是 cairo toy text API 字体渲染。对于严重的(即不是基本的拉丁文本)字体渲染,您应该使用PangoCairo

标签: c++ utf-8 cairo


【解决方案1】:

根据the Cairo documentation,不建议使用 Cairo 进行文本操作。他们将其描述为玩具文本 API,并推荐使用 Pango 文本,正如您已经提到的可能性。我不能肯定地说这是你的问题,但在链接页面的描述中,它说 Cairo 不能很好地处理字体问题。您选择的字体可能不支持此字符。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2014-05-05
    • 2021-05-01
    • 1970-01-01
    • 2016-08-10
    相关资源
    最近更新 更多