Quartz 2D 概述 —— Quartz 2D編程指導翻譯 第2篇

本文翻譯自蘋果官方文檔:原文地址

Quartz 2D 概述

Quartz 2D 是一個二維的繪畫引擎,在Mac OS X和iOS環境下可以使用,它在內核之外。你可以使用Quartz 2D 的API來完成各種各樣的操作,例如:基于路徑的繪圖、透明度繪圖、陰影繪圖、透明圖層、顏色管理、抗鋸齒渲染、PDF操作等。Quartz 2D能夠盡可能的發揮出圖形硬件的性能。

頁(The Page)

Quartz 2D 使用畫家模型來成像。在這個模型中,每次連續的繪圖操作都將一個叫做“油漆”的圖層應用到一個通常叫做“頁”的輸出“畫布”上。在“頁”上的“油漆”能夠被后續的的繪圖操作所覆蓋。只有你進行額外的繪圖操作,原先在“頁”上的物體才會被修改。這個模型允許你使用少量的基本元素來構建復雜精細的圖像。

圖 1-1 展示了畫家模型的工作原理。按照從左往右的順序繪制圖形,可以看到結果是不一樣的,因此繪制的順序在這個模型中是十分重要的。

圖 1-1 畫家模型

這個“頁”或許是一個真正的紙張(輸出設備是打印機);也或許是一個虛擬的紙張(輸出設備是一個PDF文件);還可能是一個位圖圖像。準確的說,這個“頁”的本質取決于你使用的繪圖上下文的類型。

繪圖地點:圖形上下文(The Graphics Context)

圖形上下文(graphics context)是一個未開源的數據類型(CGContextRef),它包含了Quartz需要繪圖到輸出設備(如:PDF文件、bitmap、顯示器上的一個窗口等等)的信息。在圖形上下文中的信息,不僅包含繪圖需要的參數,還包含了特定設備的繪圖信息。所有Quartz需要的信息都包含在一個圖形上下文中。

你可以把一個圖形上下文看做繪圖的地方,就像 圖 1-2展示的那樣。當你使用Quartz繪圖時,所有指定設備的特征都包含在你使用的那個特定的圖形上下文中。換句話說,你可以僅僅為繪圖這一系列操作提供不同的圖形上下文就可以在不同的設備上繪制出相同的內容。

圖 1-2 Quartz 繪圖地點

下列這些圖形上下文在你的應用程序用可以使用:

  • 位圖圖形上下文允許你在位圖(bitmap)中繪制RGB顏色、CMYK顏色或者灰階(grayscale)。位圖是像素的矩形陣列(或柵格),每個像素表示圖像中的點。位圖圖像也稱為采樣圖像。請參閱創建位圖圖形上下文
  • PDF圖形上下文允許你創建PDF文件。在一個PDF文件中,你的繪圖操作將被當做一系列命令被保留。PDF文件和位圖有以下明顯的不同點:
    • PDF文件可能擁有多個page(不像位圖只有一個)。
    • 當您從不同設備上的PDF文件中繪制頁面時,生成的映像將針對該設備的顯示特性進行優化。
    • 被繪制的PDF文件天生就可以在不損失細節的情況下無限放大和縮小,而位圖圖像的分辨率直接影響感官效果。
    • 詳見創建PDF圖形上下文
  • 窗口(window)圖形上下文是一個你可以在窗口中繪制的圖形上下文。注意,因為Quartz 2D是一個圖形引擎而不是窗口管理系統,你可以使用應用程序的框架來獲取一個窗口的圖形上下文。詳見:在Mac OS X下創建窗口圖形上下文
  • 圖層上下文(CGLayerRef)是一個和其他圖形上下文關聯的一個離屏繪制的目標。它是為了在將圖層繪制到創建它的圖形上下文的最佳性能而設計的。在離屏繪制中,圖層上下文是一個比位圖圖形上下文更好的選擇。詳見:核心圖層繪制
  • 當你在Mac OS X中想要打印時,可以把要打印的內容發送到一個叫做PostScript 圖形上下文中,這個PostScript 圖形上下文在printing框架中。詳見:獲取打印的圖形上下文

Quartz 2D 中的數據類型

Quartz 2D 的 API 定義了大量的不透明數據類型。因為這些 API 是Core Graphics 框架中的一部分,所以這些數據類型按照慣例都是以“CG”開頭的。

為了實現指定的繪圖輸出,你的應用程序運行Quartz 2D,并使用這些閉源的數據類型來創造對象。圖 1-3 展示了一系列你能夠使用Quartz 2D提供的三種數據類型來實現的不同效果。例如:

  • 你能夠通過創建PDF page對象,應用旋轉變換,并將其繪制到圖形上下文中來實現旋轉并展示一個PDF page的效果。
  • 你能夠通過創建一個樣章對象并定義構成圖案的形狀來進行相應的繪制。
  • 你可以通過創建陰影對象來填充具有軸向或者鏡像的漸變區域。
圖 1-3 基本類型的繪制展示

Quartz 2D中包含的閉源數據類型如下:

圖形狀態(Graphics States)

Quartz繪制的結果是根據存儲在當前圖形狀態(Graphics States)中的參數決定的。圖形狀態(Graphics States)中所包含的參數在相應的情況下會被用于繪制過程,這些參數的值決定了Quartz如何去渲染繪圖的結果。例如:當你使用一個函數去設置了填充顏色(fill color),那么你就修改了存儲在當前圖形狀態(Graphics States)中一個參數的值。其他一些經常使用的參數有:線寬、當前的位置、字體的大小等等。

圖形上下文(Graphics Context)使用的方式來存儲圖形狀態(Graphics States)。當Quartz創建圖形上下文時,這個棧是空的。當你保存保存圖形狀態(Graphics States)時,Quartz將當前圖形狀態的復制壓入到棧中。當你重置圖形狀態時,Quartz將棧頂的圖形狀態推出。推出之后棧中的圖形狀態成為了當前的圖形狀態

如果想要保存當前的圖形狀態,那么可以使用CGContextSaveGState函數;如果要重置之前的圖形狀態,那么可以使用CGContextRestoreGState

需要注意的是,不是所有當前繪畫涉及的內容都屬于圖形狀態的。例如:當前的路徑(path)就不是圖形狀態中的內容,因此,當你保存圖形狀態時并不會保存這些不屬于圖形狀態的內容。表 1-1 列舉了當調用保存狀態方法時會保存的圖形狀態參數:

表 1-1 圖形狀態相關參數

參數名 詳細講述章節
當前變換矩陣(Current transformation matrix 也即CTM) 變換
剪輯區域(Clipping area) 路徑
線:寬度、連接、線帽、虛線、連接線的斜接限制(miter limit) 路徑
曲線的平直度 路徑
抗鋸齒設置 圖形上下文
顏色:填充和描邊設置 顏色和色域
Alpha值(透明度) 顏色和色域
渲染意圖 顏色和色域
色域:填充和描邊設置 顏色和色域
文字:字體、大小、間距、繪制模式 文字(Text)
混色模式 路徑位圖圖像與圖像遮罩

Quartz 2D 的坐標系

如圖1-4 所示,這個坐標系定義了位置的范圍,用它可以描述需要被繪制圖形的大小和位置。你可以在用戶空間坐標系統(user-space coordinate system)中指定位置和大小,簡稱為用戶空間(user space)。這個坐標系被定義為浮點值。

圖 1-4 Quartz的坐標系

因為不同的設備具有不同的底層繪圖方式,所以圖形的位置和大小必須由這些獨立的設備單獨定義和管理。例如:一個屏幕可能能夠展示超過96個像素每英寸,而一個打印機能夠展示超過300個像素每英寸。如果以設備的級別來定義坐標系,那么繪制到該坐標系的圖形不能在視覺效果一致的情況下重新繪制到其他的設備上,它不是太大就是太小。

Quartz用一個單獨的坐標系使得設備變得獨立。利用當前變換矩陣(CTM)能夠將用戶空間(user-space)的坐標系映射成當前輸出設備的坐標系。矩陣是數學上的一個結構,用它來描述一系列相等關系是非常有效率的。當前變換矩陣(CTM)是一個特殊的矩陣,叫做仿射變換,仿射變換將一個坐標系的很多點映射到另一個坐標系的其他對應的點(通過平移、旋轉、縮放等操作)。

當前轉換矩陣(CTM)還有一個次要的目的:可以使用它改變對象的繪制。例如:繪制一個傾斜45°的盒子,你僅僅需要在繪制之前旋轉當前的坐標系(CTM),Quartz 繪制的輸出就自動使用了旋轉之后的坐標系。

一個點在用戶空間(user space)下用一個坐標對表示 (x,y) ,其中x代表水平(左和右)的距離,y代表距離垂直(上和下)的距離。坐標系的原點是(0,0),它在"頁"的左下角,如 圖1-4 所示。在Quartz默認的坐標系中,x從左向右時增加,y從下向上時增加。

在某些技術條件下所使用的圖形上下文的坐標系和Quartz默認的坐標系是不同的。對于Quartz而言,這些坐標系是被修改過的,因此當使用Quartz來進行一些繪圖操作時,就應該對此進行相應的補償。最常見的補償方式就是:將原點由左下角移動到左上角,并且y軸的正半軸方向向下延伸。下面是一些使用到上述坐標系的地方:

  • 在 MAC OS X 中,當一個NSView的子類重寫了它的isFlipped方法并返回YES時。
  • 在iOS中,使用UIView獲取到的繪圖上下文。
  • 在iOS中,使用UIGraphicsBeginImageContextWithOptions方法獲取到的繪圖上下文。

UIKit之所以返回給Quartz的坐標系與Quartz默認的坐標系不一致,是因為UIKit默認使用另一個不同的坐標系。為了使得創建的Quartz上下文符合這個默認的坐標系,UIKit對其應用了變換。如果你想使用相同的坐標系來繪制UIView和一個PDF圖形上下文(由Quartz創建并使用Quartz默認的坐標系),你可以對PDF的圖形上下文進行相應的變換(將原點轉換到左上角,將y軸以scale的方式乘以-1)。

使用縮放(scale)的方式使y軸的方向改變后同時也改變了Quartz中一些默認的東西。例如:如果你在這樣的圖形上下文中調用CGContextDrawImage來繪制圖片時,它會被這個變換所修改。同樣,路徑繪制中所接受的參數(如弧的順時針、逆時針方向)也可能會被修改。如 圖1-5 所示,在默認的坐標系中是順時針繪制的,但是應用上述變換后,繪制的方向就變成了逆時針。

圖 1-5 修改坐標系后創建了一個鏡像的繪制

在Quartz繪制時,這些變換的應用完全取決于你的應用程序。例如,如果你想將一個圖片或者PDF正確的繪制到圖形上下文中,你的應用程序需要暫時調整該圖形上下文的CTM。在iOS中如果你使用一個UIImage對象來包裝你創建的一個CGImage對象,你不需要修改CTM,UIImage自動修改了UIKit對坐標系應用的變換。

重點:上述討論對于你想直接在iOS上使用Quartz是十分重要的,但是它還不足夠讓你徹底理解。在iOS 3.2和之后的版本中,當UIKit為你的應用程序創建圖形上下文時,它同時也附加了額外的操作使得這個圖形上下文能夠符合UIKit默認的坐標系標準。特別地,不受CTM影響的樣章(Patterns)和陰影(shadows)被單獨調整,使得它們的約定與UIKit的坐標系匹配。在這種情況下,您的應用程序不能使用等效的CTM機制來更改由Quartz創建的上下文以匹配UIKit提供的上下文的行為;您的應用程序必須意識到它正在什么樣的上下文中進行繪制,并調整其行為以符合上下文的期望。

內存管理:對象的歸屬(Object Ownership)

Quartz使用了Core Foundation 內存管理模型,即對象使用了引用計數。當創建時,這些對象具有1的引用計數。你可以通過調用函數增加對象的引用計數來保留這個對象,也可以調用相應的函數較少對象的引用計數來釋放對象。當對象的引用計數減少到0時,這個對象就會被釋放,這個模型提供了安全的對象共享方式。

你應當記住這三個簡單的規則:

  • 如果你創建或者拷貝(copy)了一個對象,那么你就擁有它,因此你必須要釋放(release)它。也就是說,如果你使用帶有"Create"或者"Copy"這樣名字的方法獲得了這個對象,當你不需要使用時你就必須釋放它(release),否則就會造成內存泄露。
  • 如果你沒有使用帶有"Create"或者"Copy"這樣名字的方法獲得了一個對象,那么你就沒有擁有這個對象的引用,因此不能釋放這個對象。這個對象在將來會被它的擁有者所釋放。
  • 如果你沒有擁有一個對象,但是你需要讓他在你的使用周期內存在時,你必須retain它,當你不用時還要release它。你可以使用Quartz提供的方法來retain和release一個對象。例如:你得到一個CGColorspace對象,你可以使用CGColorSpaceRetain 方法和 CGColorSpaceRelease 方法來retain和release這個你需要的對象。同樣,你也可以使用 Core Foundation 提供的 CFReatinCFRelease 方法,但是你一定要注意不要對這些方法傳入NULL。

上一章:Core Graphics(Quartz 2D)編程簡介
下一章:圖形上下文(Graphics Context)

最后編輯于
?著作權歸作者所有,轉載或內容合作請聯系作者
平臺聲明:文章內容(如有圖片或視頻亦包括在內)由作者上傳并發布,文章內容僅代表作者本人觀點,簡書系信息發布平臺,僅提供信息存儲服務。
  • 序言:七十年代末,一起剝皮案震驚了整個濱河市,隨后出現的幾起案子,更是在濱河造成了極大的恐慌,老刑警劉巖,帶你破解...
    沈念sama閱讀 228,983評論 6 537
  • 序言:濱河連續發生了三起死亡事件,死亡現場離奇詭異,居然都是意外死亡,警方通過查閱死者的電腦和手機,發現死者居然都...
    沈念sama閱讀 98,772評論 3 422
  • 文/潘曉璐 我一進店門,熙熙樓的掌柜王于貴愁眉苦臉地迎上來,“玉大人,你說我怎么就攤上這事。” “怎么了?”我有些...
    開封第一講書人閱讀 176,947評論 0 381
  • 文/不壞的土叔 我叫張陵,是天一觀的道長。 經常有香客問我,道長,這世上最難降的妖魔是什么? 我笑而不...
    開封第一講書人閱讀 63,201評論 1 315
  • 正文 為了忘掉前任,我火速辦了婚禮,結果婚禮上,老公的妹妹穿的比我還像新娘。我一直安慰自己,他們只是感情好,可當我...
    茶點故事閱讀 71,960評論 6 410
  • 文/花漫 我一把揭開白布。 她就那樣靜靜地躺著,像睡著了一般。 火紅的嫁衣襯著肌膚如雪。 梳的紋絲不亂的頭發上,一...
    開封第一講書人閱讀 55,350評論 1 324
  • 那天,我揣著相機與錄音,去河邊找鬼。 笑死,一個胖子當著我的面吹牛,可吹牛的內容都是我干的。 我是一名探鬼主播,決...
    沈念sama閱讀 43,406評論 3 444
  • 文/蒼蘭香墨 我猛地睜開眼,長吁一口氣:“原來是場噩夢啊……” “哼!你這毒婦竟也來了?” 一聲冷哼從身側響起,我...
    開封第一講書人閱讀 42,549評論 0 289
  • 序言:老撾萬榮一對情侶失蹤,失蹤者是張志新(化名)和其女友劉穎,沒想到半個月后,有當地人在樹林里發現了一具尸體,經...
    沈念sama閱讀 49,104評論 1 335
  • 正文 獨居荒郊野嶺守林人離奇死亡,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內容為張勛視角 年9月15日...
    茶點故事閱讀 40,914評論 3 356
  • 正文 我和宋清朗相戀三年,在試婚紗的時候發現自己被綠了。 大學時的朋友給我發了我未婚夫和他白月光在一起吃飯的照片。...
    茶點故事閱讀 43,089評論 1 371
  • 序言:一個原本活蹦亂跳的男人離奇死亡,死狀恐怖,靈堂內的尸體忽然破棺而出,到底是詐尸還是另有隱情,我是刑警寧澤,帶...
    沈念sama閱讀 38,647評論 5 362
  • 正文 年R本政府宣布,位于F島的核電站,受9級特大地震影響,放射性物質發生泄漏。R本人自食惡果不足惜,卻給世界環境...
    茶點故事閱讀 44,340評論 3 347
  • 文/蒙蒙 一、第九天 我趴在偏房一處隱蔽的房頂上張望。 院中可真熱鬧,春花似錦、人聲如沸。這莊子的主人今日做“春日...
    開封第一講書人閱讀 34,753評論 0 28
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽。三九已至,卻和暖如春,著一層夾襖步出監牢的瞬間,已是汗流浹背。 一陣腳步聲響...
    開封第一講書人閱讀 36,007評論 1 289
  • 我被黑心中介騙來泰國打工, 沒想到剛下飛機就差點兒被人妖公主榨干…… 1. 我叫王不留,地道東北人。 一個月前我還...
    沈念sama閱讀 51,834評論 3 395
  • 正文 我出身青樓,卻偏偏與公主長得像,于是被迫代替她去往敵國和親。 傳聞我的和親對象是個殘疾皇子,可洞房花燭夜當晚...
    茶點故事閱讀 48,106評論 2 375

推薦閱讀更多精彩內容