本文翻譯自蘋果官方文檔:原文地址
Quartz 2D 概述
Quartz 2D 是一個二維的繪畫引擎聚至,在Mac OS X和iOS環(huán)境下可以使用蝇棉,它在內(nèi)核之外搜吧。你可以使用Quartz 2D 的API來完成各種各樣的操作,例如:基于路徑的繪圖沿腰、透明度繪圖叔扼、陰影繪圖事哭、透明圖層、顏色管理瓜富、抗鋸齒渲染鳍咱、PDF操作等。Quartz 2D能夠盡可能的發(fā)揮出圖形硬件的性能与柑。
頁(The Page)
Quartz 2D 使用畫家模型來成像谤辜。在這個模型中,每次連續(xù)的繪圖操作都將一個叫做“油漆”的圖層應(yīng)用到一個通常叫做“頁”的輸出“畫布”上仅胞。在“頁”上的“油漆”能夠被后續(xù)的的繪圖操作所覆蓋。只有你進(jìn)行額外的繪圖操作剑辫,原先在“頁”上的物體才會被修改干旧。這個模型允許你使用少量的基本元素來構(gòu)建復(fù)雜精細(xì)的圖像。
圖 1-1 展示了畫家模型的工作原理妹蔽。按照從左往右的順序繪制圖形椎眯,可以看到結(jié)果是不一樣的,因此繪制的順序在這個模型中是十分重要的胳岂。
這個“頁”或許是一個真正的紙張(輸出設(shè)備是打印機(jī))编整;也或許是一個虛擬的紙張(輸出設(shè)備是一個PDF文件);還可能是一個位圖圖像乳丰。準(zhǔn)確的說掌测,這個“頁”的本質(zhì)取決于你使用的繪圖上下文的類型。
繪圖地點(diǎn):圖形上下文(The Graphics Context)
圖形上下文(graphics context)是一個未開源的數(shù)據(jù)類型(CGContextRef)产园,它包含了Quartz需要繪圖到輸出設(shè)備(如:PDF文件汞斧、bitmap、顯示器上的一個窗口等等)的信息什燕。在圖形上下文中的信息粘勒,不僅包含繪圖需要的參數(shù),還包含了特定設(shè)備的繪圖信息屎即。所有Quartz需要的信息都包含在一個圖形上下文中庙睡。
你可以把一個圖形上下文看做繪圖的地方事富,就像 圖 1-2展示的那樣。當(dāng)你使用Quartz繪圖時乘陪,所有指定設(shè)備的特征都包含在你使用的那個特定的圖形上下文中统台。換句話說,你可以僅僅為繪圖這一系列操作提供不同的圖形上下文就可以在不同的設(shè)備上繪制出相同的內(nèi)容暂刘。
下列這些圖形上下文在你的應(yīng)用程序用可以使用:
- 位圖圖形上下文允許你在位圖(bitmap)中繪制RGB顏色饺谬、CMYK顏色或者灰階(grayscale)。位圖是像素的矩形陣列(或柵格)谣拣,每個像素表示圖像中的點(diǎn)募寨。位圖圖像也稱為采樣圖像。請參閱創(chuàng)建位圖圖形上下文森缠。
- PDF圖形上下文允許你創(chuàng)建PDF文件拔鹰。在一個PDF文件中,你的繪圖操作將被當(dāng)做一系列命令被保留贵涵。PDF文件和位圖有以下明顯的不同點(diǎn):
- PDF文件可能擁有多個page(不像位圖只有一個)列肢。
- 當(dāng)您從不同設(shè)備上的PDF文件中繪制頁面時,生成的映像將針對該設(shè)備的顯示特性進(jìn)行優(yōu)化宾茂。
- 被繪制的PDF文件天生就可以在不損失細(xì)節(jié)的情況下無限放大和縮小瓷马,而位圖圖像的分辨率直接影響感官效果。
- 詳見創(chuàng)建PDF圖形上下文跨晴。
- 窗口(window)圖形上下文是一個你可以在窗口中繪制的圖形上下文欧聘。注意,因?yàn)镼uartz 2D是一個圖形引擎而不是窗口管理系統(tǒng)端盆,你可以使用應(yīng)用程序的框架來獲取一個窗口的圖形上下文怀骤。詳見:在Mac OS X下創(chuàng)建窗口圖形上下文。
- 圖層上下文(CGLayerRef)是一個和其他圖形上下文關(guān)聯(lián)的一個離屏繪制的目標(biāo)焕妙。它是為了在將圖層繪制到創(chuàng)建它的圖形上下文的最佳性能而設(shè)計的蒋伦。在離屏繪制中,圖層上下文是一個比位圖圖形上下文更好的選擇焚鹊。詳見:核心圖層繪制痕届。
- 當(dāng)你在Mac OS X中想要打印時,可以把要打印的內(nèi)容發(fā)送到一個叫做PostScript 圖形上下文中末患,這個PostScript 圖形上下文在printing框架中爷抓。詳見:獲取打印的圖形上下文。
Quartz 2D 中的數(shù)據(jù)類型
Quartz 2D 的 API 定義了大量的不透明數(shù)據(jù)類型阻塑。因?yàn)檫@些 API 是Core Graphics 框架中的一部分蓝撇,所以這些數(shù)據(jù)類型按照慣例都是以“CG”開頭的。
為了實(shí)現(xiàn)指定的繪圖輸出陈莽,你的應(yīng)用程序運(yùn)行Quartz 2D渤昌,并使用這些閉源的數(shù)據(jù)類型來創(chuàng)造對象虽抄。圖 1-3 展示了一系列你能夠使用Quartz 2D提供的三種數(shù)據(jù)類型來實(shí)現(xiàn)的不同效果。例如:
- 你能夠通過創(chuàng)建PDF page對象独柑,應(yīng)用旋轉(zhuǎn)變換迈窟,并將其繪制到圖形上下文中來實(shí)現(xiàn)旋轉(zhuǎn)并展示一個PDF page的效果。
- 你能夠通過創(chuàng)建一個樣章對象并定義構(gòu)成圖案的形狀來進(jìn)行相應(yīng)的繪制忌栅。
- 你可以通過創(chuàng)建陰影對象來填充具有軸向或者鏡像的漸變區(qū)域车酣。
Quartz 2D中包含的閉源數(shù)據(jù)類型如下:
- CGPathRef,用于你要填充或者描邊的矢量圖形索绪。詳見:路徑湖员。
- CGImageRef,通常代表根據(jù)您提供的樣本數(shù)據(jù)來表示位圖圖像和位圖圖像遮罩瑞驱。詳見:位圖圖像和圖像遮罩娘摔。
- CGLayerRef,通常代表一個可以重復(fù)使用的或者離屏繪制的圖層唤反。詳見:核心圖形圖層繪制凳寺。
- CGPatternRef,用于重復(fù)繪制彤侍。詳見:樣章肠缨。
- CGShadingRef和CGGradientRef,用于繪制漸變盏阶。詳見:漸變晒奕。
- CGFunctionRef,用于定義具有任意數(shù)量的浮點(diǎn)類型的參數(shù)的回調(diào)函數(shù)般哼。當(dāng)你在創(chuàng)建一個漸變時會用到這種數(shù)據(jù)類型吴汪,詳見:漸變惠窄。
- CGColorRef和CGColorSpaceRef蒸眠,用來告知Quartz如何解析顏色。詳見:顏色和色域杆融。
- CGImageSourceRef和CGImageDestinationRef楞卡,用來從Quartz中導(dǎo)入或?qū)С鰯?shù)據(jù)。詳見:Quartz 2D的數(shù)據(jù)管理和Image I/O 編程指導(dǎo)脾歇。
- CGFontRef蒋腮,用于繪制文字。詳見:文字(Text)藕各。
- CGPDFDictionaryRef,CGPDFObjectRef,CGPDFPageRef,CGPDFStream,CGPDFStringRef和CGPDFArrayRef池摧,這些類提供了獲取PDF元數(shù)據(jù)的方法。詳見:PDF文檔的創(chuàng)建激况、預(yù)覽和轉(zhuǎn)換作彤。
- CGPDFSacnnerRef和CGPDFContenStreamRef膘魄,用來解析PDF元數(shù)據(jù)。詳見:PDF文檔解析竭讳。
- CGPSConverterRef创葡,被用來將PostScript轉(zhuǎn)換成PDF,iOS中不可用绢慢。詳見:PostScript 轉(zhuǎn)換灿渴。
圖形狀態(tài)(Graphics States)
Quartz繪制的結(jié)果是根據(jù)存儲在當(dāng)前圖形狀態(tài)(Graphics States)中的參數(shù)決定的。圖形狀態(tài)(Graphics States)中所包含的參數(shù)在相應(yīng)的情況下會被用于繪制過程胰舆,這些參數(shù)的值決定了Quartz如何去渲染繪圖的結(jié)果骚露。例如:當(dāng)你使用一個函數(shù)去設(shè)置了填充顏色(fill color),那么你就修改了存儲在當(dāng)前圖形狀態(tài)(Graphics States)中一個參數(shù)的值思瘟。其他一些經(jīng)常使用的參數(shù)有:線寬荸百、當(dāng)前的位置、字體的大小等等滨攻。
圖形上下文(Graphics Context)使用棧的方式來存儲圖形狀態(tài)(Graphics States)够话。當(dāng)Quartz創(chuàng)建圖形上下文時,這個棧是空的光绕。當(dāng)你保存保存圖形狀態(tài)(Graphics States)時女嘲,Quartz將當(dāng)前圖形狀態(tài)的復(fù)制壓入到棧中。當(dāng)你重置圖形狀態(tài)時诞帐,Quartz將棧頂?shù)?strong>圖形狀態(tài)推出欣尼。推出之后棧中的圖形狀態(tài)成為了當(dāng)前的圖形狀態(tài)。
如果想要保存當(dāng)前的圖形狀態(tài)停蕉,那么可以使用CGContextSaveGState函數(shù)愕鼓;如果要重置之前的圖形狀態(tài),那么可以使用CGContextRestoreGState慧起。
需要注意的是菇晃,不是所有當(dāng)前繪畫涉及的內(nèi)容都屬于圖形狀態(tài)的。例如:當(dāng)前的路徑(path)就不是圖形狀態(tài)中的內(nèi)容蚓挤,因此磺送,當(dāng)你保存圖形狀態(tài)時并不會保存這些不屬于圖形狀態(tài)的內(nèi)容。表 1-1 列舉了當(dāng)調(diào)用保存狀態(tài)方法時會保存的圖形狀態(tài)參數(shù):
表 1-1 圖形狀態(tài)相關(guān)參數(shù)
參數(shù)名 | 詳細(xì)講述章節(jié) |
---|---|
當(dāng)前變換矩陣(Current transformation matrix 也即CTM) | 變換 |
剪輯區(qū)域(Clipping area) | 路徑 |
線:寬度灿意、連接估灿、線帽、虛線缤剧、連接線的斜接限制(miter limit) | 路徑 |
曲線的平直度 | 路徑 |
抗鋸齒設(shè)置 | 圖形上下文 |
顏色:填充和描邊設(shè)置 | 顏色和色域 |
Alpha值(透明度) | 顏色和色域 |
渲染意圖 | 顏色和色域 |
色域:填充和描邊設(shè)置 | 顏色和色域 |
文字:字體馅袁、大小、間距荒辕、繪制模式 | 文字(Text) |
混色模式 | 路徑汗销、位圖圖像與圖像遮罩 |
Quartz 2D 的坐標(biāo)系
如圖1-4 所示芒粹,這個坐標(biāo)系定義了位置的范圍,用它可以描述需要被繪制圖形的大小和位置大溜。你可以在用戶空間坐標(biāo)系統(tǒng)(user-space coordinate system)中指定位置和大小化漆,簡稱為用戶空間(user space)。這個坐標(biāo)系被定義為浮點(diǎn)值钦奋。
因?yàn)椴煌脑O(shè)備具有不同的底層繪圖方式座云,所以圖形的位置和大小必須由這些獨(dú)立的設(shè)備單獨(dú)定義和管理。例如:一個屏幕可能能夠展示超過96個像素每英寸付材,而一個打印機(jī)能夠展示超過300個像素每英寸朦拖。如果以設(shè)備的級別來定義坐標(biāo)系,那么繪制到該坐標(biāo)系的圖形不能在視覺效果一致的情況下重新繪制到其他的設(shè)備上厌衔,它不是太大就是太小璧帝。
Quartz用一個單獨(dú)的坐標(biāo)系使得設(shè)備變得獨(dú)立。利用當(dāng)前變換矩陣(CTM)能夠?qū)⒂脩艨臻g(user-space)的坐標(biāo)系映射成當(dāng)前輸出設(shè)備的坐標(biāo)系富寿。矩陣是數(shù)學(xué)上的一個結(jié)構(gòu)睬隶,用它來描述一系列相等關(guān)系是非常有效率的。當(dāng)前變換矩陣(CTM)是一個特殊的矩陣页徐,叫做仿射變換苏潜,仿射變換將一個坐標(biāo)系的很多點(diǎn)映射到另一個坐標(biāo)系的其他對應(yīng)的點(diǎn)(通過平移、旋轉(zhuǎn)变勇、縮放等操作)恤左。
當(dāng)前轉(zhuǎn)換矩陣(CTM)還有一個次要的目的:可以使用它改變對象的繪制。例如:繪制一個傾斜45°的盒子搀绣,你僅僅需要在繪制之前旋轉(zhuǎn)當(dāng)前的坐標(biāo)系(CTM)飞袋,Quartz 繪制的輸出就自動使用了旋轉(zhuǎn)之后的坐標(biāo)系。
一個點(diǎn)在用戶空間(user space)下用一個坐標(biāo)對表示 (x,y) 链患,其中x代表水平(左和右)的距離巧鸭,y代表距離垂直(上和下)的距離。坐標(biāo)系的原點(diǎn)是(0,0)锣险,它在"頁"的左下角蹄皱,如 圖1-4 所示览闰。在Quartz默認(rèn)的坐標(biāo)系中芯肤,x從左向右時增加,y從下向上時增加压鉴。
在某些技術(shù)條件下所使用的圖形上下文的坐標(biāo)系和Quartz默認(rèn)的坐標(biāo)系是不同的崖咨。對于Quartz而言,這些坐標(biāo)系是被修改過的油吭,因此當(dāng)使用Quartz來進(jìn)行一些繪圖操作時击蹲,就應(yīng)該對此進(jìn)行相應(yīng)的補(bǔ)償署拟。最常見的補(bǔ)償方式就是:將原點(diǎn)由左下角移動到左上角,并且y軸的正半軸方向向下延伸歌豺。下面是一些使用到上述坐標(biāo)系的地方:
- 在 MAC OS X 中推穷,當(dāng)一個NSView的子類重寫了它的isFlipped方法并返回YES時。
- 在iOS中类咧,使用UIView獲取到的繪圖上下文馒铃。
- 在iOS中,使用UIGraphicsBeginImageContextWithOptions方法獲取到的繪圖上下文痕惋。
UIKit之所以返回給Quartz的坐標(biāo)系與Quartz默認(rèn)的坐標(biāo)系不一致区宇,是因?yàn)閁IKit默認(rèn)使用另一個不同的坐標(biāo)系。為了使得創(chuàng)建的Quartz上下文符合這個默認(rèn)的坐標(biāo)系值戳,UIKit對其應(yīng)用了變換议谷。如果你想使用相同的坐標(biāo)系來繪制UIView和一個PDF圖形上下文(由Quartz創(chuàng)建并使用Quartz默認(rèn)的坐標(biāo)系),你可以對PDF的圖形上下文進(jìn)行相應(yīng)的變換(將原點(diǎn)轉(zhuǎn)換到左上角堕虹,將y軸以scale的方式乘以-1)卧晓。
使用縮放(scale)的方式使y軸的方向改變后同時也改變了Quartz中一些默認(rèn)的東西。例如:如果你在這樣的圖形上下文中調(diào)用CGContextDrawImage來繪制圖片時赴捞,它會被這個變換所修改禀崖。同樣,路徑繪制中所接受的參數(shù)(如弧的順時針螟炫、逆時針方向)也可能會被修改波附。如 圖1-5 所示,在默認(rèn)的坐標(biāo)系中是順時針繪制的昼钻,但是應(yīng)用上述變換后掸屡,繪制的方向就變成了逆時針。
在Quartz繪制時然评,這些變換的應(yīng)用完全取決于你的應(yīng)用程序仅财。例如,如果你想將一個圖片或者PDF正確的繪制到圖形上下文中碗淌,你的應(yīng)用程序需要暫時調(diào)整該圖形上下文的CTM盏求。在iOS中如果你使用一個UIImage對象來包裝你創(chuàng)建的一個CGImage對象,你不需要修改CTM亿眠,UIImage自動修改了UIKit對坐標(biāo)系應(yīng)用的變換碎罚。
重點(diǎn):上述討論對于你想直接在iOS上使用Quartz是十分重要的,但是它還不足夠讓你徹底理解纳像。在iOS 3.2和之后的版本中荆烈,當(dāng)UIKit為你的應(yīng)用程序創(chuàng)建圖形上下文時,它同時也附加了額外的操作使得這個圖形上下文能夠符合UIKit默認(rèn)的坐標(biāo)系標(biāo)準(zhǔn)。特別地憔购,不受CTM影響的樣章(Patterns)和陰影(shadows)被單獨(dú)調(diào)整宫峦,使得它們的約定與UIKit的坐標(biāo)系匹配。在這種情況下玫鸟,您的應(yīng)用程序不能使用等效的CTM機(jī)制來更改由Quartz創(chuàng)建的上下文以匹配UIKit提供的上下文的行為;您的應(yīng)用程序必須意識到它正在什么樣的上下文中進(jìn)行繪制导绷,并調(diào)整其行為以符合上下文的期望。
內(nèi)存管理:對象的歸屬(Object Ownership)
Quartz使用了Core Foundation 內(nèi)存管理模型屎飘,即對象使用了引用計數(shù)诵次。當(dāng)創(chuàng)建時,這些對象具有1的引用計數(shù)枚碗。你可以通過調(diào)用函數(shù)增加對象的引用計數(shù)來保留這個對象逾一,也可以調(diào)用相應(yīng)的函數(shù)較少對象的引用計數(shù)來釋放對象。當(dāng)對象的引用計數(shù)減少到0時肮雨,這個對象就會被釋放遵堵,這個模型提供了安全的對象共享方式。
你應(yīng)當(dāng)記住這三個簡單的規(guī)則:
- 如果你創(chuàng)建或者拷貝(copy)了一個對象怨规,那么你就擁有它陌宿,因此你必須要釋放(release)它。也就是說波丰,如果你使用帶有"Create"或者"Copy"這樣名字的方法獲得了這個對象壳坪,當(dāng)你不需要使用時你就必須釋放它(release),否則就會造成內(nèi)存泄露。
- 如果你沒有使用帶有"Create"或者"Copy"這樣名字的方法獲得了一個對象掰烟,那么你就沒有擁有這個對象的引用爽蝴,因此不能釋放這個對象。這個對象在將來會被它的擁有者所釋放纫骑。
- 如果你沒有擁有一個對象蝎亚,但是你需要讓他在你的使用周期內(nèi)存在時,你必須retain它先馆,當(dāng)你不用時還要release它发框。你可以使用Quartz提供的方法來retain和release一個對象。例如:你得到一個CGColorspace對象煤墙,你可以使用CGColorSpaceRetain 方法和 CGColorSpaceRelease 方法來retain和release這個你需要的對象梅惯。同樣,你也可以使用 Core Foundation 提供的 CFReatin 和 CFRelease 方法仿野,但是你一定要注意不要對這些方法傳入NULL铣减。
上一章:Core Graphics(Quartz 2D)編程簡介
下一章:圖形上下文(Graphics Context)