用於產生一致輸出的矢量繪圖庫——cairo

寫在文章前面:cairo 的目標是以跨平臺的方式在打印機和屏幕上產生相同的輸出,它正在成爲 Linux® 圖形領域的重要軟件。GNOME、GTK+、Pango 等許多軟件已經使用了它提供的 2D 功能。

本文參考自IBM技術主題

CAIRO的優點和用途:
cairo 是一個免費的矢量繪圖軟件庫,它可以繪製多種輸出格式。cairo 支持許多平臺,包括 Linux、BSD、Microsoft® Windows® 和 OSX(BeOS 和 OS2 後端也正在開發)。Linux 繪圖可以通過 X Window 系統、Quartz、圖像緩衝格式或 OpenGL 上下文來實現。另外,cairo 還支持生成 PostScript 或 PDF 輸出,從而產生高質量的打印結果。在理想情況下,cairo 的用戶可以在打印機和屏幕上獲得非常接近的輸出效果。

本文將向您介紹 cairo,以及它對應用程序的意義。本文的示例將產生一個 pdf、ps、png、svg 和 gtk 窗口,顯示的圖形是 IBM 徽標。

cairo 的一項主要設計目標是提供儘可能接近的輸出。這種一致的輸出使 cairo 非常適合 GUI 工具集編程和跨平臺應用程序開發。使用同一個繪圖庫打印高分辨率的屏幕和繪製屏幕內容,這種功能具有顯著的優點。
另外,在支持的每種目標平臺上,cairo 嘗試智能化地使用底層硬件和軟件支持。高質量矢量圖形和高性能的結合使 cairo 成爲優秀的 UNIX® 繪圖系統。

cairo 是用 C 編寫的,但是爲大多數常用的語言提供了綁定。選用 C 語言有助於創建新的綁定,同時在進行 C 語言調用時可以提供高性能。應該特別注意 Python 綁定,它支持快速原型開發,而且降低了學習 cairo 繪圖 API 的門檻。

計算機繪圖系統和體系結構很早就出現了,cairo 的設計借鑑了 PostScript 和 PDF 模型的許多經驗。cairo 之所以借鑑 PostScript 和 Portable Document Format(PDF)方法是因爲,它們都使用數學語句定義圖像。由於用幾何方法表示圖像,所以可以在任何時候在一定範圍內計算幾何描述,從而重新創建整個圖像(或一部分圖像)。圖形的幾何性質被表示爲點、曲線和直線(這些元素構成了矢量)。
因爲可以通過重新計算數學描述來重新繪製圖像或其組成部分,所以在對圖像進行放大、縮小或變換時不會出現分辨率損失。但是,矢量繪圖也有一些限制。例如,如果對矢量圖像進行極高比例的縮放,超出了大多數人實際需要的範圍,就可能導致失真。在放大時,由於計算中要對誤差進行舍入,所以某些直線可能看起來不正確。在縮小時,某些直線可能會無法看到或難以分辨。

cairo 採用矢量繪圖還有一個優點:矢量圖像往往比較小。這是因爲用相當簡單的數學表達式就可以表達大量信息。矢量繪圖的優點是繪圖過程相當簡單。由繪圖庫負責將點、線以及相關表達式轉換爲用戶可以看到的東西。

描述曲線的表達式稱爲 Bezier 曲線或路徑,這個名稱源自數學家 Pierre Bezier。Bezier 曲線由至少兩個錨點(anchor point)組成,在錨點之間還有一個或多個點,這些點稱爲控制點(handle)。移動控制點就可以改變曲線的形狀。如果您用過 Photoshop 或 GIMP 這樣的工具,那麼可能熟悉這種曲線。但是,在使用那些工具時,最終保存的圖形格式可能是位圖!文件的格式決定是否保留 Bezier 路徑信息,還是在給定的範圍內計算它並以位圖格式保存計算結果。

到編寫本文時,可用的 cairo 綁定包括 C++、Ruby、Perl、Java™ 語言和 .Net/mono 等等。這些綁定處於不同的開發狀態,成熟度各不相同;可以通過 cairo 項目主頁瞭解它們的最新情況(參考 官方網站 )。目前,Python 和 C++ 綁定似乎在開放源碼社區中得到了廣泛採用。

正如前面提到的,一些圖形工具集也爲 cairo 提供了綁定,這使 cairo 開發更加簡便了。2.8 之後的 Gtk+ 版本包含對 cairo 的完整支持,而且以後的 GTK 版本一直選用 cairo 作爲基本繪圖系統。另外,GNUstep 和 FLTK 等工具集已經開始支持用 cairo 來滿足圖形呈現需求。

如果您打算進行任何跨平臺開發,而且需要對繪圖操作和組合進行低層控制,那麼選用 cairo 作爲繪圖 API 是非常合適的。如果需要跨平臺功能,但是不需要低層繪圖控制,那麼可以使用在 cairo 之上構建的一些繪圖庫。


爲什麼要學習一種新的繪圖模型?

坦率地說,我認爲目前的開放源碼解決方案在幾個方面存在欠缺。xprint 的優點是提供了統一的顯示和打印 API,但是它通常作爲單獨的服務器進程運行,而且它的 API 很糟糕。libgnomeprint 提供單獨的打印和顯示模型,但是打印和繪圖 API 的分離使屏幕和打印機的呈現效果產生差異。

cairo 從以前的繪圖庫借鑑了許多經驗,而且從一開始就以實現統一 API 爲設計目標。


cairo 呈現目標
cairo 可以呈現以下輸出格式:

  • X Window System(如果可能的話,會利用 Render 擴展)
  • OpenGL(使用 glitz 後端)
  • In-Memory Images(pixbuffs 等等)
  • PostScript(適用於打印)
  • PDF(Portable Document Format)文件
  • SVG(Scalable Vector Graphics)格式

但是,並非所有呈現目標都產生相同的效果。儘管 cairo 力求在各種後端上產生相同的輸出,但是每種後端各有優勢。例如,PDF 後端會盡可能使用矢量計算(只在必要時生成圖像),而 PostScript 後端實際上會爲每個頁面生成一個大圖像。

cairo 中的呈現模型受到許多原有技術的影響。cairo 採用了 PostScript 中的路徑、筆畫(stroke)和填充(fill)概念,還實現了 PDF 和現代 X 服務器實現的呈現擴展中的 Porter-Duff 圖像組合技術。另外,cairo 還實現了剪切、蒙板和漸變等補充特性。


cairo 的實際應用情況
許多有影響力的開放源碼項目已經採用了 cairo,cairo 已經成爲 Linux 圖形領域的重要軟件。已經採用 cairo 的重要項目包括:

  • Gtk+,一個廣受喜愛的跨平臺圖形工具集
  • Pango,一個用於佈置和呈現文本的免費軟件庫,它主要用於實現國際化
  • Gnome,一個免費的桌面環境
  • Mozilla,一個跨平臺的 Web 瀏覽器基礎結構,Firefox 就是在這個基礎結構上構建的
  • OpenOffice.org,一個可以與 Microsoft Office 匹敵的免費辦公套件

用 cairo 進行概念性繪圖
在用 cairo 進行繪圖時,最簡單的操作就像手工繪畫時一樣:選擇繪圖介質,選擇畫筆,選擇顏色,考慮線條的佈局,然後進行實際繪製。cairo 文檔通過與畫家的作畫過程進行類比來介紹 cairo 操作,下面的說明也採用這種方式。

對於畫家來說,最容易的事兒通常是選擇空白的繪圖介質。在現實世界中,藝術家可以選擇在紙上、畫布上甚至牆上作畫。在 cairo 中,也必須選擇空白的繪圖介質。在用 cairo 進行繪圖時,需要設置一個 cairo 上下文,這是主對象。在這個上下文中,可以選擇目標外表,比如 PostScript 文件、PDF 文檔或屏幕圖像。這樣就可以選擇我們要在什麼東西上進行繪圖。

現在考慮畫家的下一項任務:選擇畫筆。畫家往往花費相當長的時間來選擇形狀和大小合適的畫筆。在 cairo 中,也有畫筆形狀的概念,這由筆畫寬度來表達。不同的筆畫寬度會產生不同粗細的線條。
接下來,cairo 用戶需要以精確的座標來表達繪圖操作,這一點與現實世界中的繪畫過程不同。藝術家只需將畫筆放在紙上的大概位置,但是計算機必須知道進行繪圖的 x 和 y 座標。
設置了畫筆和開始繪圖的位置之後,就需要想像筆畫的形狀。簡單的圖形可能由直線組成,但是與現實的畫家一樣,也可以繪製曲線和弧線。

最後,必須定義筆畫終止的位置。同樣,這個位置也要用一對 (x,y) 座標來指定。
另外,還可以給繪製的對象塗上顏色。按照 cairo 術語,這稱爲填充(fill)。對於上面描述的每種操作,cairo 中都有對應的簡便的 API 實現。後面會介紹其中一些 API。

這些基本操作可以幫助您構建一些非常複雜的圖形。甚至可以使用 cairo 執行畫家無法輕鬆完成的工作,比如對現有的圖形進行放大等轉換,或者將圖形移動到虛擬紙張上的其他地方。

GIMP 或 Photoshop 也允許執行其中的許多操作,但是 cairo 是不同的:cairo 是一種編程式繪圖方式。GIMP 和 Photoshop “在幕後” 使用 cairo 這樣的工具來實現繪圖。在用這些工具進行繪圖時,通過鼠標操作自動設置座標點和工具類型(比如方框),並通過 GUI 環境選擇畫筆和筆畫寬度。如IBM給出的示例代碼所示(鏈接),cairo 需要顯式的交互,比如 “使用筆畫寬度 1 繪製一個弧線,半徑爲 10,中心在位置 z”。


正確的 cairo 術語

在討論任何技術時,都要使用正確的術語。cairo API 的術語分爲三類:核心繪圖術語、外表術語和與字體相關的術語(更多細節見 參考資料)。

首先,cairo 有一個繪圖上下文(drawing context),這相當於畫家的畫布。上下文是 cairo_t 類型的,要呈現圖形,就必須有一個上下文。在繪圖上下文上的常見操作是繪製 Bezier 圖形、直線和曲線。表示一系列曲線和相關數據的 cairo 術語是路徑(path)。可以繪製這些路徑,並設置筆畫寬度或填充。
使用一個非常簡單的 API 將座標轉換爲路徑。這個 API 非常有意義,因爲它使我們不必考慮線性代數或圖形學課本中討論的複雜的轉換矩陣。可以對 cairo 繪圖操作執行任何轉換,包括對圖形或部分圖形進行剪切、縮放或旋轉。通過指定點來繪製每條路徑。cairo 按照將點連接起來的方法執行操作。在後面將提供一個示例。

接下來,討論各種 cairo 外表類型。有幾種 cairo 外表類型,它們分別對應一種輸出目標。cairo 外表(surface)是執行繪圖的位置。具體地說,有用於圖像(內存緩衝區)的外表、用於 Open GL 的 glitz 外表、用於呈現文檔的 PDF 和 PostScript 外表以及用於直接執行繪圖的 XLib 和 Win32 外表。這些外表類型都派生自外表基類型 cairo_surface_t

在 cairo 中,模式(pattern)是一種可以讀取的內容,它用作繪圖操作的源或蒙板。cairo 中的模式可以是實體模式、基於外表的模式甚至逐變模式。

到目前爲止,我們只談到了筆畫路徑。但是,筆畫路徑一般只能產生不怎麼有趣的線條圖。實際上,簡單的線條筆畫只是 cairo 中的 5 種基本繪圖操作之一。這 5 種操作是:

  • cairo_stroke
  • cairo_fill
  • cairo_show_text/cairo_show_glyphs
  • cairo_paint
  • cairo_mask

儘管簡單的線條繪圖很方便,但是它們的表達能力不夠強,不足以表示字體這樣的複雜圖形。cairo 爲字體提供了一個基類 cairo_font_face_t。cairo 支持可縮放字體,其中包含給定字體大小的緩存標準。另外,可以用各種字體選項控制如何顯示給定的字體。在使用 cairo 時,在 UNIX 上常用的字體是 Freetype 字體,在 Windows 平臺上使用 Win32 字體。


cairo 的發展過程
cairo 的版本號採用與 Linux 內核相似的規則 —— 也就是,奇數版本是實驗性的開發版本,不適合在生產環境中使用。偶數版本是穩定版本:最初的 1.0 版本主要關注順利地向用戶提供 API 和產生高質量輸出。1.2 API 完善了幾個開發不太完整的後端,當前的 1.4 系列主要關注優化和添加新功能。

cairo 的開發人員提供了一些出色的示例代碼片段,演示了 cairo API 的各種功能(參考官方示例)。所以不必等待 cairo 的下一個版本了,現在就下載並試用當前版本!

提供一些參考資料:

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章