You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Linux下C语言结合Cairo与CUPS实现多页带背景打印问题求解

解决方案

1. 多页统一背景实现

将背景绘制逻辑封装为独立公用函数,每次新建页面后先绘制背景,再绘制当前页的前景文本即可。cairo_show_page()会完成上一页输出并重置上下文为空白新页,重复调用背景绘制函数就能实现每页背景一致。

2. A4尺寸背景适配+低版本Cairo兼容方案

不需要操作图片表面的缩放属性,直接调整绘制上下文的变换矩阵即可实现缩放,该方案兼容Cairo 1.8.8版本,配合滤波参数设置可达到和cairo_surface_set_device_scale完全一致的画质,解决你之前找到的缩放函数画质差的问题。

关键修改代码

封装背景绘制函数

#define WIDTH  595
#define HEIGHT 842

// 背景绘制公用函数,支持自适应A4,可选择是否保持图片宽高比
void draw_background(cairo_t *cr, cairo_surface_t *png_surf, int png_w, int png_h) {
    cairo_save(cr); // 保存当前上下文状态,避免缩放影响后续文本绘制
    
    // 计算缩放比例
    double scale_x = (double)WIDTH / png_w;
    double scale_y = (double)HEIGHT / png_h;
    // 如需保持图片宽高比不拉伸,取消下面一行的注释即可
    // double scale = scale_x < scale_y ? scale_x : scale_y; scale_x = scale; scale_y = scale;
    // 如需保持宽高比且背景居中,取消下面两行注释
    // double offset_x = (WIDTH - png_w * scale_x) / 2;
    // double offset_y = (HEIGHT - png_h * scale_y) / 2;
    // cairo_translate(cr, offset_x, offset_y);
    
    cairo_scale(cr, scale_x, scale_y);
    // 设置双线性滤波,解决缩放模糊问题
    cairo_pattern_set_filter(cairo_get_source(cr), CAIRO_FILTER_BILINEAR);
    cairo_set_operator(cr, CAIRO_OPERATOR_DEST_OVER);
    cairo_set_source_surface(cr, png_surf, 0, 0);
    cairo_paint(cr);
    
    cairo_restore(cr); // 恢复上下文状态
}

简化多页绘制逻辑

int main(int argc, char** argv) {
    int widthPng, heightPng;
    if (argc!= 2){
       fprintf (stderr, "usage: %s word\n", argv[0]);
       return 1;
    }

    char* tmpfilename = tempnam(NULL,NULL);
    cairo_surface_t* surface = cairo_ps_surface_create(tmpfilename, WIDTH, HEIGHT);
    cairo_t *context = cairo_create(surface);

    // 全局只加载一次背景图,无需每页重复加载
    cairo_surface_t* surface_png = cairo_image_surface_create_from_png("background-img.png");
    if (surface_png == NULL || cairo_surface_status (surface_png)) {
       printf("***** load error *****\n");
       return 1;
    }
    widthPng = cairo_image_surface_get_width(surface_png);
    heightPng = cairo_image_surface_get_height(surface_png);

    // 绘制第一页
    cairo_select_font_face(context, "mono", CAIRO_FONT_SLANT_NORMAL, CAIRO_FONT_WEIGHT_NORMAL);
    cairo_set_font_size(context, 30);
    cairo_move_to(context, WIDTH/2, HEIGHT/2);
    cairo_show_text(context, argv[1]);
    const double pattern[] = {15.0, 10.0};
    cairo_set_dash(context, pattern, 2, 0);
    cairo_set_line_width(context, 5);
    cairo_rectangle(context, WIDTH*0.33, HEIGHT*0.33, WIDTH*0.5, WIDTH*0.5);
    cairo_stroke(context);
    // 调用公用函数绘制背景
    draw_background(context, surface_png, widthPng, heightPng);

    // 切换到第二页
    cairo_show_page(context);

    // 绘制第二页,仅修改前景内容即可
    cairo_select_font_face(context, "mono", CAIRO_FONT_SLANT_NORMAL, CAIRO_FONT_WEIGHT_NORMAL);
    cairo_set_font_size(context, 30);
    cairo_move_to(context, WIDTH/2, HEIGHT/2);
    cairo_show_text(context, "text over second page");
    draw_background(context, surface_png, widthPng, heightPng);

    // 收尾逻辑
    cairo_show_page(context);
    cairo_destroy(context);
    cairo_surface_flush(surface);
    cairo_surface_destroy(surface);
    cairo_surface_destroy(surface_png);

    cupsPrintFile("Cups-PDF", tmpfilename, "cairo PS", 0, NULL);
    unlink(tmpfilename);
    return 0;
}

方案优势

  • 完全兼容Cairo 1.8.8版本,不需要依赖cairo_surface_set_device_scale接口
  • 双线性滤波保证缩放画质和原生设备缩放完全一致,无模糊锯齿
  • 无需创建中间缩放表面,内存占用更低、绘制效率更高
  • 背景逻辑复用,新增页面仅需修改前景内容,维护成本更低

内容的提问来源于stack exchange,提问作者famedoro

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.10.04 01:36:02