pangocairo:透明记录表面变色

pangocairo: discolouration on transparent recording surfaces

当我使用 Pango 在透明的 Cairo 记录表面上绘制文本时,文本的颜色变得相当严重,尤其是在半透明的抗锯齿区域。例如,this image has the correct (top) and incorrect (bottom) rendition of some text. (Segment of previous image zoomed in).

显然,我的问题是如何在使用透明记录表面时获得正确的色彩再现。至少,我 假设 这个问题与我对 pangocairo 管道不太了解有关。如果它是 Pango 或 Cairo 中的错误,请告诉我。

用于生成上图的代码:

#include <cairo/cairo.h>
#include <pango/pangocairo.h>

int main(int argc, char **argv)
{
    cairo_surface_t *canvas = cairo_image_surface_create(CAIRO_FORMAT_ARGB32,
        320, 60);
    cairo_t *cctx = cairo_create(canvas);

    cairo_surface_t *surf = cairo_recording_surface_create(
        CAIRO_CONTENT_COLOR_ALPHA, NULL);
    cairo_t *ctx = cairo_create(surf);
    PangoFontDescription *fd = pango_font_description_new();
    PangoLayout *layout = pango_cairo_create_layout(ctx);
    PangoAttrList *attrs = pango_attr_list_new();
    PangoAttribute *at;

    cairo_set_source_rgba(cctx, 1, 1, 1, 1);
    cairo_paint(cctx);
    cairo_translate(cctx, 16, 8);

    pango_font_description_set_family(fd, "DejaVu Sans Mono");
    pango_layout_set_font_description(layout, fd);

    pango_layout_set_text(layout, "Bless the Maker and His water", -1);
    pango_layout_set_attributes(layout, attrs);

    at = pango_attr_foreground_new(0, 0xffff, 0xffff);
    pango_attr_list_change(attrs, at);
    at = pango_attr_foreground_alpha_new(0xffff);
    pango_attr_list_change(attrs, at);

    cairo_save(ctx);
    cairo_set_source_rgba(ctx, 1, 1, 1, 1);
    cairo_set_operator(ctx, CAIRO_OPERATOR_SOURCE);
    cairo_paint(ctx);
    cairo_restore(ctx);

    pango_cairo_update_layout(ctx, layout);
    pango_cairo_show_layout(ctx, layout);

    cairo_set_source_surface(cctx, surf, 0, 0);
    cairo_paint(cctx);

    cairo_save(ctx);
    cairo_set_source_rgba(ctx, 0, 0, 0, 0);
    cairo_set_operator(ctx, CAIRO_OPERATOR_SOURCE);
    cairo_paint(ctx);
    cairo_restore(ctx);

    pango_cairo_update_layout(ctx, layout);
    pango_cairo_show_layout(ctx, layout);

    cairo_translate(cctx, 0, 24);
    cairo_set_source_surface(cctx, surf, 0, 0);
    cairo_paint(cctx);

    cairo_surface_write_to_png(canvas, "test.png");

    g_object_unref(layout);
    pango_attr_list_unref(attrs);
    pango_font_description_free(fd);
    cairo_destroy(ctx);
    cairo_destroy(cctx);
    cairo_surface_destroy(surf);
    cairo_surface_destroy(canvas);

    return 0;
}


更新:这似乎是由视频管道中的某些东西引起的,并且可能是一个错误。我可以在两个使用 AMD 视频卡的机器上重现这一点,但不能在一个使用 nVidia 卡的机器上重现。我将此打开以防万一有人知道修复方法。

首先:您的示例代码没有在此处重现问题。结果图像中没有"color fringes"。

如果您允许我猜测:Cairo 为您假定 RGB 的子像素顺序。根据 cairo_subpixel_order_t 的文档,这仅用于 CAIRO_ANTIALIAS_SUBPIXEL。因此,我建议您这样做:

cairo_font_options_t *opts = cairo_get_font_options(some_cairo_context);
cairo_font_options_set_antialias(opts, CAIRO_ANTIALIAS_GRAY); // or _NONE
cairo_set_font_options(some_cairo_context, opts);
cairo_font_options_destroy(opts);

原来 @uli-schlachter 几乎 正确:您必须在 Pango 布局对象上设置抗锯齿选项:

PangoContext *pctx = pango_layout_get_context(layout);
cairo_font_options_t *opts = cairo_font_options_create();
cairo_font_options_set_antialias(opts, CAIRO_ANTIALIAS_GRAY);
pango_cairo_context_set_font_options(pctx, opts);
cairo_font_options_destroy(opts);