版本記錄
版本號 | 時間 |
---|---|
V1.0 | 2018.09.08 |
前言
Quartz 2D
框架相信大家都知道,也都一直在使用。Quartz 2D
的API是純C語言的,它是一個二維繪圖引擎,同時支持iOS和Mac系統。Quartz 2D
的API來自于Core Graphics
框架,數據類型和函數基本都以CG作為前綴,接下來幾篇我們就一起來看一下這個框架。感興趣可以看上面幾篇文章。
1. Quartz 2D編程指南 (一) —— 簡介(一)
2. Quartz 2D編程指南 (二) —— Quartz 2D概覽(二)
3. Quartz 2D編程指南 (三) —— 圖形上下文(三)
4. Quartz 2D編程指南 (四) —— Paths路徑(一)
5. Quartz 2D編程指南 (五) —— Paths路徑(二)
6. Quartz 2D編程指南 (六) —— 顏色和顏色空間(一)
7. Quartz 2D編程指南 (七) —— 變換(一)
8. Quartz 2D編程指南 (八) —— Patterns圖案樣式(一)
9. Quartz 2D編程指南 (九) —— 陰影(一)
10. Quartz 2D編程指南 (十) —— 漸變(一)
11. Quartz 2D編程指南 (十一) —— 透明層(一)
12. Quartz 2D編程指南 (十二) —— Quartz 2D中的數據管理(一)
13. Quartz 2D編程指南 (十三) —— 位圖圖像和圖像蒙版(一)
14. Quartz 2D編程指南 (十四) —— 位圖圖像和圖像蒙版(二)
Core Graphics Layer Drawing - Core Graphics圖層繪制
CGLayer對象(CGLayerRef數據類型)允許您的應用程序使用圖層進行繪制。
圖層適用于以下內容:
- 您計劃重復使用的高質量的繪圖離線渲染。例如,您可能正在構建場景并計劃重用相同的背景。將背景場景繪制到圖層,然后在需要時繪制圖層。一個額外的好處是您不需要知道繪制到圖層的顏色空間或設備相關信息。
- 重復繪圖。例如,您可能希望創建一個由反復繪制的相同項組成的圖案。將項目繪制到圖層,然后重復繪制圖層,如圖12-1所示。您重復繪制的任何Quartz對象(包括
CGPath
,CGShading
和CGPDFPage
對象) - 如果將其繪制到CGLayer,都可以從改進的性能中受益。請注意,圖層不僅適??用于屏幕繪圖;您可以將它用于非面向屏幕的圖形上下文,例如PDF圖形上下文。 - 緩沖。雖然您可以為此目的使用圖層,但您不需要這樣做,因為
Quartz Compositor
不需要您的緩沖。如果必須繪制到緩沖區,請使用圖層而不是位圖圖形上下文。
CGLayer
對象和透明層與CGContext
函數創建的CGPath
對象和路徑并行。 對于CGLayer
或CGPath
對象,您可以繪制到抽象目標,然后可以將完整的繪制繪制到另一個目標,例如顯示或PDF。 當您繪制透明圖層或使用繪制路徑的CGContext函數時,您可以直接繪制到圖形上下文所表示的目標。 沒有用于組裝繪畫的中間抽象目的地。
How Layer Drawing Works - 圖層繪制原理
由CGLayerRef數據類型表示的層旨在實現最佳性能。如果可能,Quartz使用適合與其關聯的Quartz圖形上下文類型的機制來緩存CGLayer對象。例如,與視頻卡相關聯的圖形上下文可以緩存視頻卡上的圖層,這使得繪制圖層中的內容比渲染從位圖圖形上下文構造的類似圖像快得多。因此,與位圖圖形上下文相比,圖層通常是屏幕外繪制的更好選擇。
所有Quartz繪圖函數都繪制到圖形上下文。圖形上下文提供了目的地的抽象,使您可以從目的地詳細信息中解放出來,例如其分辨率。您在用戶空間中工作,Quartz執行必要的轉換以將繪圖正確呈現到目的地。使用CGLayer對象進行繪制時,還可以繪制到圖形上下文。圖12-1說明了圖層繪制的必要步驟。
所有圖層繪制都以圖形上下文開始,您可以使用CGLayerCreateWithContext函數從該圖形上下文創建CGLayer對象。用于創建CGLayer對象的圖形上下文通常是窗口圖形上下文。 Quartz創建一個圖層,使其具有圖形上下文的所有特征 - 分辨率,顏色空間和圖形狀態設置。如果您不想使用圖形上下文的大小,則可以為圖層提供大小。在圖12-2中,左側顯示了用于創建圖層的圖形上下文。右側框中的灰色部分標記為CGLayer對象,表示新創建的圖層。
在繪制到圖層之前,必須通過調用函數CGLayerGetContext來獲取與圖層關聯的圖形上下文。此圖形上下文與用于創建圖層的圖形上下文相同。只要用于創建圖層的圖形上下文是窗口圖形上下文,那么盡可能將CGLayer圖形上下文緩存到GPU。圖12-2右側框的白色部分表示新創建的圖層圖形上下文。
您可以繪制到圖層的圖形上下文,就像繪制到任何圖形上下文一樣,將圖層的圖形上下文傳遞給繪圖函數。圖12-2顯示了繪制到圖層上下文的葉子形狀。
當您準備使用圖層的內容時,可以調用函數CGContextDrawLayerInRect或CGContextDrawLayerAtPoint,將圖層繪制到圖形上下文中。通常,您將繪制到用于創建圖層對象的相同圖形上下文,但您不需要。您可以將圖層繪制到任何圖形上下文,請記住圖層繪制具有用于創建圖層對象的圖形上下文的特征,這可能會施加某些約束(例如,性能或分辨率)。例如,與屏幕相關聯的層可以高速緩存在視頻硬件中。如果目標上下文是打印或PDF上下文,則可能需要將其從圖形硬件提取到內存,從而導致性能不佳。
圖12-2顯示了圖層的內容 - 重復繪制的葉子到用于創建圖層對象的圖形上下文。在釋放CGLayer對象之前,您可以多次重復使用圖層中的圖形。
提示:如果要合成圖形的某些部分以實現遮蔽一組對象等效果,請使用透明度圖層。 (請參閱Transparency Layers。)如果要在屏幕外繪制或需要重復繪制相同的內容時,請使用
CGLayer
對象。
Drawing with a Layer - 使用圖層進行繪制
您需要執行以下部分中描述的任務以使用CGLayer對象進行繪制:
- 1) Create a CGLayer Object Initialized with an Existing Graphics Context
- 2) Get a Graphics Context for the Layer
- 3) Draw to the CGLayer Graphics Context
- 4) Draw the Layer to the Destination Graphics Context
請參閱示例:Example: Using Multiple CGLayer Objects to Draw a Flag以獲取詳細的代碼示例。
1. Create a CGLayer Object Initialized with an Existing Graphics Context - 創建使用現有圖形上下文初始化的CGLayer對象
函數CGLayerCreateWithContext返回使用現有圖形上下文初始化的圖層。 該圖層繼承了圖形上下文的所有特征,包括顏色空間,大小,分辨率和像素格式。 稍后,當您將圖層繪制到目標時,Quartz會自動將圖層顏色與目標上下文匹配。
函數CGLayerCreateWithContext有三個參數:
- 從中創建圖層的圖形上下文。 通常,您傳遞窗口圖形上下文,以便稍后可以在屏幕上繪制圖層。
- 圖層相對于圖形上下文的大小。 圖層可以與圖形上下文相同或更小。 如果以后需要檢索圖層大小,可以調用函數CGLayerGetSize。
- 輔助字典。 此參數當前未使用,因此傳遞
NULL
。
2. Get a Graphics Context for the Layer - 獲取圖層的圖形上下文
Quartz
總是繪制到圖形上下文。 現在您有了一個圖層,您必須創建一個與圖層關聯的圖形上下文。 您在圖層圖形上下文中繪制的任何內容都是圖層的一部分。
函數CGLayerGetContext將圖層作為參數,并返回與圖層關聯的圖形上下文。
3. Draw to the CGLayer Graphics Context - 繪制CGLayer圖形上下文
獲取與圖層關聯的圖形上下文后,可以執行圖層圖形上下文中的任何繪圖。 您可以打開PDF文件或圖像文件,并將文件內容繪制到圖層。 您可以使用任何Quartz 2D函數來繪制矩形,線條和其他繪圖基元。 圖12-3顯示了繪制矩形和線到圖層的示例。
例如,要將填充的矩形繪制到CGLayer圖形上下文,可以調用函數CGContextFillRect,提供從函數CGLayerGetContext獲取的圖形上下文。 如果圖形上下文名為myLayerContext
,則函數調用如下所示:
CGContextFillRect(myLayerContext,myRect)
4. Draw the Layer to the Destination Graphics Context - 將圖層繪制到目標圖形上下文
準備好將圖層繪制到目標圖形上下文時,可以使用以下任一函數:
- CGContextDrawLayerInRect,它將圖層繪制到指定矩形中的圖形上下文。
- CGContextDrawLayerAtPoint,它將圖層繪制到指定點的圖形上下文。
通常,您提供的目標圖形上下文是窗口圖形上下文,它與您用于創建圖層的圖形上下文相同。 圖12-4顯示了重復繪制圖12-3所示圖層圖的結果。 要實現圖案效果,可以重復調用圖層繪制函數 - CGContextDrawLayerAtPoint或CGContextDrawLayerInRect - 每次更改偏移量。 例如,您可以調用函數CGContextTranslateCTM
以在每次繪制圖層時更改坐標空間的原點。
注意:您不需要將圖層繪制到用于初始化圖層的相同圖形上下文。 但是,如果將圖層繪制到另一個圖形上下文,則會對繪圖施加原始圖形上下文的任何限制。
Example: Using Multiple CGLayer Objects to Draw a Flag - 示例:使用多個CGLayer對象繪制旗幟
本節介紹如何使用兩個CGLayer對象繪制屏幕上圖12-5所示的國旗。 首先,您將看到如何將國旗縮減為簡單的繪圖基元,然后您將查看完成繪圖所需的代碼。
從在屏幕上繪制它的角度來看,旗幟有三個部分:
- 紅色和白色條紋的圖案。您可以將圖案縮小為單個紅色條紋,因為對于屏幕繪圖,您可以采用白色背景。您創建一個紅色矩形,然后在各種偏移處重復繪制矩形,以創建美國國旗所需的七個紅色條紋。層是重復繪圖的理想選擇。您將紅色矩形繪制到圖層,然后在屏幕上繪制七次圖層。
- 一個藍色的矩形。你需要一次藍色矩形,所以使用一個層是沒有好處的。在繪制藍色矩形時,請直接在屏幕上繪制。
- 50顆白色星星的圖案。像紅色條紋一樣,一層是繪制星星的理想選擇。您創建一個概述星形的路徑,然后用白色填充路徑。將一個星形繪制到一個圖層,然后將該圖層繪制50次,每次調整偏移量以獲得適當的間距。
圖12-2中的代碼產生如圖12-5所示的輸出。列表后面會顯示每個編號行代碼的詳細說明。列表相當長,因此您可能需要打印說明,以便在查看代碼時可以閱讀。從Cocoa應用程序中調用myDrawFlag
例程。應用程序傳遞窗口圖形上下文和矩形,該矩形指定與窗口圖形上下文關聯的視圖的大小。
注意:在調用此程序或使用
CGLayer
對象的任何例程之前,必須檢查以確保系統運行的是Mac OS X v10.4
或更高版本,并且具有支持使用CGLayer對象的圖形卡。
// Listing 12-1 Code that uses layers to draw a flag
void myDrawFlag (CGContextRef context, CGRect* contextRect)
{
int i, j,
num_six_star_rows = 5,
num_five_star_rows = 4;
CGFloat start_x = 5.0,// 1
start_y = 108.0,// 2
red_stripe_spacing = 34.0,// 3
h_spacing = 26.0,// 4
v_spacing = 22.0;// 5
CGContextRef myLayerContext1,
myLayerContext2;
CGLayerRef stripeLayer,
starLayer;
CGRect myBoundingBox,// 6
stripeRect,
starField;
// ***** Setting up the primitives *****
const CGPoint myStarPoints[] = {{ 5, 5}, {10, 15},// 7
{10, 15}, {15, 5},
{15, 5}, {2.5, 11},
{2.5, 11}, {16.5, 11},
{16.5, 11},{5, 5}};
stripeRect = CGRectMake (0, 0, 400, 17); // stripe// 8
starField = CGRectMake (0, 102, 160, 119); // star field// 9
myBoundingBox = CGRectMake (0, 0, contextRect->size.width, // 10
contextRect->size.height);
// ***** Creating layers and drawing to them *****
stripeLayer = CGLayerCreateWithContext (context, // 11
stripeRect.size, NULL);
myLayerContext1 = CGLayerGetContext (stripeLayer);// 12
CGContextSetRGBFillColor (myLayerContext1, 1, 0 , 0, 1);// 13
CGContextFillRect (myLayerContext1, stripeRect);// 14
starLayer = CGLayerCreateWithContext (context,
starField.size, NULL);// 15
myLayerContext2 = CGLayerGetContext (starLayer);// 16
CGContextSetRGBFillColor (myLayerContext2, 1.0, 1.0, 1.0, 1);// 17
CGContextAddLines (myLayerContext2, myStarPoints, 10);// 18
CGContextFillPath (myLayerContext2); // 19
// ***** Drawing to the window graphics context *****
CGContextSaveGState(context); // 20
for (i=0; i< 7; i++) // 21
{
CGContextDrawLayerAtPoint (context, CGPointZero, stripeLayer);// 22
CGContextTranslateCTM (context, 0.0, red_stripe_spacing);// 23
}
CGContextRestoreGState(context);// 24
CGContextSetRGBFillColor (context, 0, 0, 0.329, 1.0);// 25
CGContextFillRect (context, starField);// 26
CGContextSaveGState (context); // 27
CGContextTranslateCTM (context, start_x, start_y); // 28
for (j=0; j< num_six_star_rows; j++) // 29
{
for (i=0; i< 6; i++)
{
CGContextDrawLayerAtPoint (context,CGPointZero,
starLayer);// 30
CGContextTranslateCTM (context, h_spacing, 0);// 31
}
CGContextTranslateCTM (context, (-i*h_spacing), v_spacing); // 32
}
CGContextRestoreGState(context);
CGContextSaveGState(context);
CGContextTranslateCTM (context, start_x + h_spacing/2, // 33
start_y + v_spacing/2);
for (j=0; j< num_five_star_rows; j++) // 34
{
for (i=0; i< 5; i++)
{
CGContextDrawLayerAtPoint (context, CGPointZero,
starLayer);// 35
CGContextTranslateCTM (context, h_spacing, 0);// 36
}
CGContextTranslateCTM (context, (-i*h_spacing), v_spacing);// 37
}
CGContextRestoreGState(context);
CGLayerRelease(stripeLayer);// 38
CGLayerRelease(starLayer); // 39
}
這是代碼的作用:
- 1) 聲明第一個星的水平位置的變量。
- 2) 聲明第一個星的垂直位置的變量。
- 3) 聲明標志上紅色條紋之間間距的變量。
- 4) 聲明標志上星星之間水平間距的變量。
- 5) 為旗幟上的星星之間的垂直間距聲明一個變量。
- 6) 聲明矩形,指定將旗幟繪制到的位置(邊界框),條帶圖層和星形區域。
- 7) 聲明一個點數組,指定追蹤一顆星的線。
- 8) 創建一個單個條帶形狀的矩形。
- 9) 創建一個矩形,該矩形是星形區域的形狀。
- 10) 創建一個邊界框,其大小與傳遞給
myDrawFlag
例程的窗口圖形上下文相同。 - 11) 創建一個使用傳遞給
myDrawFlag
例程的窗口圖形上下文初始化的圖層。 - 12) 獲取與該圖層關聯的圖形上下文。您將使用此圖層進行條紋繪制。
- 13) 將填充顏色設置為與條帶圖層關聯的圖形上下文的不透明紅色。
- 14) 填充表示一個紅色條紋的矩形。
- 15) 創建另一個使用傳遞給
myDrawFlag
例程的窗口圖形上下文初始化的圖層。 - 16) 獲取與該圖層關聯的圖形上下文。您將使用此圖層進行星形繪制。
- 17) 將填充顏色設置為與星形圖層關聯的圖形上下文的不透明白色。
- 18) 將
myStarPoints
數組定義的10行添加到與星形圖層關聯的上下文中。 - 19) 填充路徑,該路徑由剛剛添加的10行組成。
- 20) 保存Windows圖形上下文的圖形狀態。您需要這樣做是因為您將重復繪制相同的條帶,但位于不同的位置。
- 21) 設置循環,迭代7次,對于旗幟上的每個紅色條帶一次。
- 22) 繪制條紋圖層(由單個紅色條紋組成)。
- 23) 轉換當前變換矩陣,使原點位于必須繪制下一個紅色條紋的位置。
- 24) 將圖形狀態恢復為繪制條紋之前的狀態。
- 25) 將填充顏色設置為星形區域的適當藍色陰影。請注意,此顏色的不透明度為1.0。雖然此示例中的所有顏色都是不透明的,但它們并非必須如此。您可以使用部分透明的顏色通過分層繪圖創建漂亮的效果。回想一下,alpha值為0.0指定透明色。
- 26) 用藍色填充星場矩形。您可以將此矩形直接繪制到窗口圖形上下文中。如果您只繪制一次,請不要使用圖層。
- 27) 保存窗口圖形上下文的圖形狀態,因為您將轉換CTM以正確定位星星。
- 28) 平移CTM,使原點位于星形區域,位于第一個(底部)行的第一個星形(左側)。
- 29) 這個和下一個for循環設置代碼重復繪制星形層,因此標志上的五個奇數行每個包含六個星。
- 30) 將星形圖層繪制到窗口圖形上下文中。回想一下,星形層包含一顆白星。
- 31) 定位CTM以使原點向右移動以準備繪制下一個星形。
- 32) 定位CTM以使原點向上移動以準備繪制下一行星。
- 33) 平移CTM,使原點位于星形區域,位于第二個星形(左側)的底部。注意,偶數行相對于奇數行偏移。
- 34) 這個和下一個for循環設置代碼重復繪制星形層,因此旗幟上的四個偶數行每個包含五個星。
- 35) 將星形圖層繪制到窗口圖形上下文中。
- 36) 定位CTM以使原點向右移動以準備繪制下一個星形。
- 37) 定位CTM以使原點向下并向左,以準備繪制下一行星。
- 38) 釋放條帶層。
- 39) 釋放星形圖層。
后記
本篇主要講述了Core Graphics圖層繪制,感興趣的給個贊或者關注~~~