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) ' Pi
TYPE arc_seg_data
AS cairo_t PTR c_t
AS 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_t
WITH *seg
cairo_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 WITH
cairo_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 background
cairo_paint(.c_t) ' fill page
cairo_set_line_width(.c_t, 0.5)
VAR f = 0.3 * Pag_W
.xc = f
.yc = f
FOR z AS INTEGER = 0 TO 1 ' two center points
.ri = 0.1 * f
FOR j AS INTEGER = 1 TO 5 STEP 1 ' five radius
.ra = .ri + 0.35 * f / j
FOR 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 / 2
arc_seg(seg)
NEXT
.ri = .ra
NEXT
' cairo_stroke(.c_t)
.yc = Pag_H - f
.xc = Pag_W - f
NEXT
cairo_set_font_size (.c_t, 0.15 * f)
DIM AS cairo_font_extents_t fe ' font data
cairo_font_extents (.c_t, @fe)
DIM AS cairo_text_extents_t te ' text size
cairo_text_extents (.c_t, t, @te)
cairo_move_to (.c_t, _ ' lower left corner of text
Pag_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 WITH
cairo_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) + 1
SCREENRES S_W, S_H, 32
VAR c_s_t = cairo_image_surface_create_for_data( _
SCREENPTR, CAIRO_FORMAT_ARGB32, _
S_W, S_H, S_W * LEN(single))
SCREENLOCK
DoDrawing(c_s_t)
SCREENUNLOCK
SLEEP
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_t
SELECT 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 ELSE
c_s_t = cairo_ps_surface_create(fname, Pag_W, Pag_H)
END SELECT
DoDrawing(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 text
p = PDF_new()
'' open new PDF file
if (PDF_open_file(p, "pdflib_test.pdf") = -1) then
print "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 read
sleep
end 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 then
print "Error: Couldn't read image file """ & logofilename & """"
else
w = 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 text
textx = 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的。