c - c 用 cairo 和 cups 打印更多页面
问题描述
我需要在linux环境下的C中,以图像为背景打印文档。我找到了一个使用 Cairo 矢量图形库编写 PostScript 的示例,然后将其发送到 CUPS 进行打印。我修改了初始源代码以将其与背景图像 (background-img.png) 集成。
要打印的文本不止一页,我想知道如何在多个页面上打印,保持相同的图像作为背景并只更改前景文本?如何调整背景图像的大小以匹配 A4 页面的大小?
这是用作起点的代码:
// compile with:
// gcc -Wall -o cairo_print_png cairo_print_png.c `pkg-config --cflags --libs cairo` `cups-config --cflags --libs`
#include <stdio.h>
#include <cairo.h>
#include <cairo-ps.h>
#include <cups/cups.h>
// A4 width, height in points, from GhostView manual:
// http://www.gnu.org/software/gv/manual/html_node/Paper-Keywords-and-paper-size-in-points.html
#define WIDTH 595
#define HEIGHT 842
int main(int argc, char** argv) {
int widthPng, heightPng;
if (argc!= 2){
fprintf (stderr, "usage: %s word\n", argv[0]);
return 1;
}
// setup
char* tmpfilename = tempnam(NULL,NULL);
cairo_surface_t* surface = cairo_ps_surface_create(tmpfilename,
WIDTH,
HEIGHT);
cairo_t *context = cairo_create(surface);
// draw some text
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]); // the text we got as a parameter
// draw a dotted box
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);
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");
}
widthPng = cairo_image_surface_get_width(surface_png);
heightPng = cairo_image_surface_get_height(surface_png);
cairo_surface_set_device_scale (surface_png,
widthPng/WIDTH*1.33,
heightPng/HEIGHT*1.29);
cairo_set_operator(context, CAIRO_OPERATOR_DEST_OVER);
cairo_set_source_surface(context, surface_png, 0, 0);
cairo_paint(context);
/*** second page ***/
{
cairo_t *cr;
cr = cairo_create (surface);
/* Duplicate the last frame onto another page. (This is just a
* way to sneak cairo_copy_page into the test).
*/
cairo_show_page (cr);
//draw text on second page
cairo_select_font_face(cr,
"mono",
CAIRO_FONT_SLANT_NORMAL,
CAIRO_FONT_WEIGHT_NORMAL);
cairo_set_font_size(cr, 30);
cairo_move_to(cr, WIDTH/2, HEIGHT/2);
cairo_show_text(cr, "text over second page");
cairo_set_operator(cr, CAIRO_OPERATOR_DEST_OVER);
cairo_set_source_surface(cr, surface_png, 0, 0);
cairo_paint(cr);
cairo_destroy (cr);
}
// finish up
cairo_show_page(context);
cairo_destroy(context);
cairo_surface_flush(surface);
cairo_surface_destroy(surface);
cairo_surface_flush(surface_png);
cairo_surface_destroy(surface_png);
// print
cupsPrintFile("Cups-PDF", tmpfilename, "cairo PS", 0, NULL);
unlink(tmpfilename);
return 0;
}
更新:我添加了“第二页”中的文字。我可以创建另一个页面,但我无法调整背景图像的大小。如何调整图像大小以适合 A4 尺寸?
更新 我使用 cairo_surface_set_device_scale 来调整图像大小,使用单声道字体使用固定宽度字体
更新
现在的问题是代码可以与 cairo-1.15.12-4 一起使用,而如果我尝试使用 cairo-1.8.8-3.1 进行编译,我会得到对 cairo_surface_set_device_scale' 的未定义引用。我能解决什么问题?目前我无法使用 rpm 更新库,因为我必须更新整个操作系统。我可以以某种方式替换cairo_surface_set_device_scale
执行相同任务的函数吗?
更新: 在开罗邮件列表中,我找到了以下功能:
cairo_surface_t *scale_to_half(cairo_surface_t *s, int orig_width, int
orig_height, double x_scale, double y_scale)
{
cairo_surface_t *result = cairo_surface_create_similar(s,
cairo_surface_get_content(s), orig_width*x_scale, orig_height*y_scale);
cairo_t *cr = cairo_create(result);
cairo_scale(cr, x_scale, y_scale);
cairo_set_source_surface(cr, s, 0, 0);
cairo_set_operator(cr, CAIRO_OPERATOR_SOURCE);
cairo_paint(cr);
cairo_destroy(cr);
return result;
}
但与 cairo_surface_set_device_scale 相比,质量非常低。
解决方案
推荐阅读
- javascript - Javascript 将 null 传递给 C# 控制器参数中的 ExpandoObject 字段
- java - 在不丢失第一个结果的情况下调用第二个 Mono 的最佳方法是什么?
- laravel - 自我引用雄辩 Laravel 报价发布
- android - 谷歌地图Android上的致命异常
- c# - 如何在游标上的最终迭代中运行代码
- php - magento 1.9 自定义邮件
- python - 将多个列表或项目添加到字典键
- java - What is the problem with parameters in the constructor of a Class in Java?
- kubernetes - Helm:如何从 repo 安装最新的 helm chart
- javascript - 你能解释一下为什么打字稿守卫不起作用