Cairo图形输出
cairo的surface可以是pixbuf, 可以是screen, 可以是png图,也可以是pdf文件 、svg文件、ps文件,定义了surface就可以用cairo_create(surface)产生cairo context, 操作cairo context就可以方便地在surface上画图,如果surface是pdf, 则直接就输出pdf文件了,画图之前不妨按标准纸张设置图的尺寸,比如A4尺寸,这样即可生成A4尺寸的 pdf 文件。
下面的freebasic示例example输出 pdf svg ps 三种格式文件:
' This is file cairo_output.bas, an example for cairo library
' (C) 2011 by Thomas[ dot ]Freiherr[ at ]gmx{ dot }net
' License GPLv 3
'
' See for details
' http://www.freebasic.net/forum/viewtopic.php?p=163599&highlight=#163599
' http://cairographics.org/documentation/#INCLUDE ONCE "cairo/cairo.bi"
#INCLUDE ONCE "cairo/cairo-pdf.bi"
#INCLUDE ONCE "cairo/cairo-ps.bi"
#INCLUDE ONCE "cairo/cairo-svg.bi"'{612, 792}, /* PAGE_SIZE_LETTER */
'{612, 1008}, /* PAGE_SIZE_LEGAL */
'{841.89, 1199.551}, /* PAGE_SIZE_A3 */
'{595.276, 841.89}, /* PAGE_SIZE_A4 */
'{419.528, 595.276}, /* PAGE_SIZE_A5 */
'{708.661, 1000.63}, /* PAGE_SIZE_B4 */
'{498.898, 708.661}, /* PAGE_SIZE_B5 */
'{522, 756}, /* PAGE_SIZE_EXECUTIVE */
'{288, 432}, /* PAGE_SIZE_US4x6 */
'{288, 576}, /* PAGE_SIZE_US4x8 */
'{360, 504}, /* PAGE_SIZE_US5x7 */
'{297, 684} /* PAGE_SIZE_COMM10 */CONST Pag_W = 595.276, Pag_H = 841.89 ' A4 format
CONST M_PI = 4 * ATN(1) ' PiTYPE arc_seg_dataAS cairo_t PTR c_tAS DOUBLE xc, yc, ri, ra, a1, a2, fg, fb
END TYPE' draw a colored circle segment / farbiges Kreissegment zeichnen
SUB arc_seg(BYVAL seg AS arc_seg_data PTR)VAR pa = NEW cairo_path_tWITH *segcairo_arc_negative(.c_t, .xc, .yc, .ri, .a2, .a1)cairo_arc(.c_t, .xc, .yc, .ra, .a1, .a2)cairo_close_path(.c_t)pa = cairo_copy_path(.c_t)cairo_set_source_rgba(.c_t, 1, .fg, .fb, 0.9)cairo_fill(.c_t)cairo_append_path(.c_t, pa)cairo_set_source_rgb(.c_t, 0.0, 0.0, 0.0)cairo_stroke(.c_t)END WITHcairo_path_destroy(pa)
END SUB' draw / zeichnen
SUB DoDrawing(BYVAL C AS cairo_surface_t PTR)VAR seg = NEW arc_seg_data, t = "Press a key to output PS, PDF and SVG."WITH *seg.c_t = cairo_create(C)cairo_set_source_rgb(.c_t, 1.0, 1.0, 1.0) ' white backgroundcairo_paint(.c_t) ' fill pagecairo_set_line_width(.c_t, 0.5)VAR f = 0.3 * Pag_W.xc = f.yc = fFOR z AS INTEGER = 0 TO 1 ' two center points.ri = 0.1 * fFOR j AS INTEGER = 1 TO 5 STEP 1 ' five radius.ra = .ri + 0.35 * f / jFOR i AS INTEGER = 0 TO 5 STEP 2 ' three segments.a1 = 60.0 * M_PI / 180 * i.a2 = 60.0 * M_PI / 180 * (i + 1).fg = .ra / f.fb = .a1 / M_PI / 2arc_seg(seg)NEXT.ri = .raNEXT
' cairo_stroke(.c_t).yc = Pag_H - f.xc = Pag_W - fNEXTcairo_set_font_size (.c_t, 0.15 * f)DIM AS cairo_font_extents_t fe ' font datacairo_font_extents (.c_t, @fe)DIM AS cairo_text_extents_t te ' text sizecairo_text_extents (.c_t, t, @te)cairo_move_to (.c_t, _ ' lower left corner of textPag_W / 2 - (te.width / 2 + te.x_bearing), _Pag_H / 2 + (te.height / 2) - fe.descent)cairo_show_text(.c_t, t)cairo_show_page(.c_t)cairo_destroy(.c_t)END WITHcairo_surface_flush(C)cairo_surface_destroy(C)
END SUB' screen output / Bildschirmausgabe
SUB write_screen()VAR S_W = CUINT(Pag_W) + 1, S_H = CUINT(Pag_H) + 1SCREENRES S_W, S_H, 32VAR c_s_t = cairo_image_surface_create_for_data( _SCREENPTR, CAIRO_FORMAT_ARGB32, _S_W, S_H, S_W * LEN(single))SCREENLOCKDoDrawing(c_s_t)SCREENUNLOCKSLEEP
END SUB' file output / Schreibt eine Datei, pdf/svg/ps je nach Endung in fname
SUB write_file(BYREF fname AS STRING = "")DIM AS cairo_surface_t PTR c_s_tSELECT CASE LCASE(RIGHT(fname, 4))CASE ".pdf"c_s_t = cairo_pdf_surface_create(fname, Pag_W, Pag_H)CASE ".svg"c_s_t = cairo_svg_surface_create(fname, Pag_W, Pag_H)CASE ELSEc_s_t = cairo_ps_surface_create(fname, Pag_W, Pag_H)END SELECTDoDrawing(c_s_t)
END SUB' main / Hauptprogramm
write_screen()VAR f = "cairo_circle."
write_file(f & "pdf")
write_file(f & "ps")
write_file(f & "svg")
END 0
以往pdf格式输出的pdflib库在windows下非常受欢迎(协议:个人可用,但商业使用需交license费,QT应该也是类似的协议约束)。freebasic对初期的pdflib-lite.h做了bi重写,这样在freebasic下能够直接操作pdflib库进行pdf编程,和cairo的surface做图有些相似之处,也是move_to , line_to 的画线,show_text写字。
网上已经找不到编译好的 pdflib.so 库了,高版本的库与自带的.bi不匹配。意味着,使用高版本的pdflib需要改写 pdflib.bi ; 使用pdflib-lite, 则需要自己编译,也需要稍改动一下 pdflib.bi。
编译:
打开终端,进入PDFlib-Lite目录,执行:
./configure
make
sudo make install
编译完成后,在/usr/local/include/freebasic下找到 pdflib.bi, 用任意一款文本编辑器打开它,然后,替换所有的 as single 为 as double
库放在 /usr/local/lib下应该可以找到,如果找不到的话,在/etc/ld.so.conf.d下写一个自己的配置文件,系统的lib搜寻路径就会带上它去找lib 。它是个文本文件,里面放的是库的路径,文件名自己起,符合操作系统要求即可。
下面的freebasic的示例程序,生成 pdflib_test.pdf 文件。
#include once "pdflib.bi"dim as PDF ptr p
dim as integer font, textx, texty, x, y, w, h, fontsize, c, image
dim as string textp = PDF_new()
'' open new PDF file
if (PDF_open_file(p, "pdflib_test.pdf") = -1) thenprint "Error: could not open PDF file. Check to see if it is open by another application"print "Press any key to end..." '' pause to allow error message to be readsleepend 1
end if'' some document information
PDF_set_info(p, "Creator", "pdflib_test.bas")
PDF_set_info(p, "Author", "GOK")
PDF_set_info(p, "Title", "FreeBASIC")'' start a new page, set font and size
PDF_begin_page(p, a4_width, a4_height)
font = PDF_findfont(p, "Helvetica-Bold", "host", 0)PDF_setfont(p, font, 12)'' Insert the logo
dim as string logofilename = exepath() & "/../../fblogo.gif"
image = PDF_open_image_file(p, "gif", logofilename, "", 0)
if image = -1 thenprint "Error: Couldn't read image file """ & logofilename & """"
elsew = PDF_get_value(p, "imagewidth", image)h = PDF_get_value(p, "imageheight", image)PDF_place_image(p, image, (a4_width - w)/2, a4_height-h-50, 1)'' Note: only close the image when you are finished with it. Keep it in'' memory if you plan on reusing it.PDF_close_image(p, image)
end if'' line drawing test
PDF_moveto(p, 25, a4_height-50 - h)
PDF_lineto(p, a4_width-50, a4_height-50 - h)
PDF_stroke(p)'' some output
texty = a4_height-50 - h -50 '' Move down from line by 50
PDF_set_text_pos(p, 50, texty)
PDF_show(p, "This is horizontal text in Helvetica-Bold") '' output texttextx = PDF_get_value(p, "textx", 0) '' determine text position
texty = PDF_get_value(p, "texty", 0) '' determine text position'' save state
PDF_save(p)
PDF_translate(p, textx, texty) '' move origin to end of text'' change coordinate system
PDF_rotate(p, -90) '' rotate coordinates
PDF_set_text_pos(p, 30, 100) '' provide for distance from horiz. text
PDF_show(p, "vertical text")'' restore saved state
PDF_restore(p)PDF_continue_text(p, "horizontal text continues")'' text in red
PDF_save(p)
PDF_set_text_pos(p, 50, 440)
PDF_setcolor(p, "both", "rgb", 1, 0, 0, 0)
PDF_show(p, "Write some text in a box (Courier 10 - left justified)")
PDF_restore(p)'' Print in a box
text = "PDF Viewers support a set of 14 core fonts which need not be embedded in any PDF file. They are:" + chr(10) + chr(13) + _"Courier, Courier-Bold, Courier-Oblique, Courier-BoldOblique, Helvetica, Helvetica-Bold, Helvetica-Oblique, " + _"Helvetica-BoldOblique, Times-Roman, Times-Bold, Times-Italic, Times-BoldItalic, Symbol & ZapfDingbats"fontsize = 10
font = PDF_findfont(p, "Courier", "host", 0)PDF_setfont(p, font, fontsize)x = 50
y = 350
w = 500
h = 7 * fontsize
c = PDF_show_boxed(p, text, x, y, w, h, "left", "")
if (c > 0 ) then'' C = number of characters truncated (0 means a fit)print "Not all characters could be placed in the box"
end if'' draw a box around text
PDF_rect(p, x-2, y-2, w+4, h+4)
PDF_stroke(p)'' tidy up
PDF_end_page(p) '' close page
PDF_close(p) '' close PDF document
PDF_delete(p) '' delete the PDF "object"print
print "pdflib_test.pdf generated."
print
print "Press any key to continue..." '' pause to allow error message to be read
sleep
用它做个简历应该还行,可能也只是方便而已,现在的浏览器差不多都可以选中后保存为pdf文件,各种office也是直接就生成了。pdf虽有许多其它功能(水印、文本框等),但用的地方好像并不多,如果只是少量页面,cairo画图生成pdf方便,它是free的。
PDFlib-Lite 源码及编译库放在CSDN 了, lib-and-so文件夹中放的是freebasic用的修改好的pdflib.bi头文件和编译好的 libpdflib.so 库及软链接 libpdf.so ,没安装编译环境的话可直接将它们分别放在 /usr/local/include/freebasic下和/usr/lib/x86_64-linux-gnu下使用。
点击链接下载PDFlib-Lite 源码及编译库