Quartz 2D 概述 —— Quartz 2D編程指導(dǎo)翻譯 第2篇

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

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é)果是不一樣的,因此繪制的順序在這個模型中是十分重要的胳岂。

圖 1-1 畫家模型

這個“頁”或許是一個真正的紙張(輸出設(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)容暂刘。

圖 1-2 Quartz 繪圖地點(diǎn)

下列這些圖形上下文在你的應(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ū)域车酣。
圖 1-3 基本類型的繪制展示

Quartz 2D中包含的閉源數(shù)據(jù)類型如下:

圖形狀態(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)值钦奋。

圖 1-4 Quartz的坐標(biāo)系

因?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)用上述變換后掸屡,繪制的方向就變成了逆時針。

圖 1-5 修改坐標(biāo)系后創(chuà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 提供的 CFReatinCFRelease 方法仿野,但是你一定要注意不要對這些方法傳入NULL铣减。

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

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末,一起剝皮案震驚了整個濱河市设预,隨后出現(xiàn)的幾起案子徙歼,更是在濱河造成了極大的恐慌犁河,老刑警劉巖鳖枕,帶你破解...
    沈念sama閱讀 206,839評論 6 482
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件魄梯,死亡現(xiàn)場離奇詭異,居然都是意外死亡宾符,警方通過查閱死者的電腦和手機(jī)酿秸,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 88,543評論 2 382
  • 文/潘曉璐 我一進(jìn)店門,熙熙樓的掌柜王于貴愁眉苦臉地迎上來魏烫,“玉大人辣苏,你說我怎么就攤上這事『灏” “怎么了稀蟋?”我有些...
    開封第一講書人閱讀 153,116評論 0 344
  • 文/不壞的土叔 我叫張陵,是天一觀的道長呐赡。 經(jīng)常有香客問我退客,道長,這世上最難降的妖魔是什么链嘀? 我笑而不...
    開封第一講書人閱讀 55,371評論 1 279
  • 正文 為了忘掉前任萌狂,我火速辦了婚禮,結(jié)果婚禮上怀泊,老公的妹妹穿的比我還像新娘茫藏。我一直安慰自己,他們只是感情好霹琼,可當(dāng)我...
    茶點(diǎn)故事閱讀 64,384評論 5 374
  • 文/花漫 我一把揭開白布务傲。 她就那樣靜靜地躺著,像睡著了一般枣申。 火紅的嫁衣襯著肌膚如雪树灶。 梳的紋絲不亂的頭發(fā)上,一...
    開封第一講書人閱讀 49,111評論 1 285
  • 那天糯而,我揣著相機(jī)與錄音天通,去河邊找鬼。 笑死熄驼,一個胖子當(dāng)著我的面吹牛像寒,可吹牛的內(nèi)容都是我干的。 我是一名探鬼主播瓜贾,決...
    沈念sama閱讀 38,416評論 3 400
  • 文/蒼蘭香墨 我猛地睜開眼诺祸,長吁一口氣:“原來是場噩夢啊……” “哼!你這毒婦竟也來了祭芦?” 一聲冷哼從身側(cè)響起筷笨,我...
    開封第一講書人閱讀 37,053評論 0 259
  • 序言:老撾萬榮一對情侶失蹤,失蹤者是張志新(化名)和其女友劉穎,沒想到半個月后胃夏,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體轴或,經(jīng)...
    沈念sama閱讀 43,558評論 1 300
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 36,007評論 2 325
  • 正文 我和宋清朗相戀三年仰禀,在試婚紗的時候發(fā)現(xiàn)自己被綠了照雁。 大學(xué)時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片。...
    茶點(diǎn)故事閱讀 38,117評論 1 334
  • 序言:一個原本活蹦亂跳的男人離奇死亡答恶,死狀恐怖饺蚊,靈堂內(nèi)的尸體忽然破棺而出,到底是詐尸還是另有隱情悬嗓,我是刑警寧澤污呼,帶...
    沈念sama閱讀 33,756評論 4 324
  • 正文 年R本政府宣布,位于F島的核電站包竹,受9級特大地震影響曙求,放射性物質(zhì)發(fā)生泄漏。R本人自食惡果不足惜映企,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 39,324評論 3 307
  • 文/蒙蒙 一悟狱、第九天 我趴在偏房一處隱蔽的房頂上張望。 院中可真熱鬧堰氓,春花似錦挤渐、人聲如沸。這莊子的主人今日做“春日...
    開封第一講書人閱讀 30,315評論 0 19
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽。三九已至囤攀,卻和暖如春软免,著一層夾襖步出監(jiān)牢的瞬間,已是汗流浹背焚挠。 一陣腳步聲響...
    開封第一講書人閱讀 31,539評論 1 262
  • 我被黑心中介騙來泰國打工膏萧, 沒想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留,地道東北人蝌衔。 一個月前我還...
    沈念sama閱讀 45,578評論 2 355
  • 正文 我出身青樓榛泛,卻偏偏與公主長得像,于是被迫代替她去往敵國和親噩斟。 傳聞我的和親對象是個殘疾皇子曹锨,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 42,877評論 2 345

推薦閱讀更多精彩內(nèi)容