CGLayer對象(CGLayerRef數(shù)據(jù)類型)允許應(yīng)用程序使用圖層進行繪制。
圖層適用于以下:
- 您計劃重復(fù)使用的繪圖的高質(zhì)量屏幕外顯示。例如,您可能正在構(gòu)建場景并計劃重復(fù)使用相同的背景。將背景場景繪制到圖層,然后在需要時繪制圖層。一個額外的好處是,您不需要知道顏色空間或設(shè)備相關(guān)的信息繪制到圖層。
- 重復(fù)繪圖。例如,您可能想要創(chuàng)建一個由重復(fù)繪制的相同項目組成的模式。將項目繪制到圖層,然后重復(fù)繪制圖層,如圖12-1所示。您反復(fù)繪制的任何Quartz對象(包括CGPath,CGShading和CGPDFPage對象)都可以通過提高性能(如果將其繪制到CGLayer)獲益。注意,圖層不僅僅用于屏幕上的繪制;您可以將其用于不面向屏幕的圖形上下文,例如PDF圖形上下文。
- 緩沖。雖然你可以使用圖層為此目的,你不應(yīng)該需要,因為石英合成器使你的部分緩沖不必要。如果必須繪制到緩沖區(qū),請使用圖層而不是位圖圖形上下文。
CGLayer對象和透明層與CGContext函數(shù)創(chuàng)建的CGPath對象和路徑并行。 在CGLayer或CGPath對象的情況下,您繪制到抽象目標(biāo),然后可以繪制完整的繪畫到另一個目的地,如顯示或PDF。 當(dāng)您繪制到透明層或使用繪制路徑的CGContext函數(shù)時,您直接繪制由圖形上下文表示的目標(biāo)。 沒有中間抽象的目的地組裝這幅畫。
圖層繪制如何工作
由CGLayerRef數(shù)據(jù)類型表示的圖層是為實現(xiàn)最佳性能而設(shè)計的。如果可能,Quartz使用適合于與其相關(guān)聯(lián)的Quartz圖形上下文類型的機制緩存CGLayer對象。例如,與視頻卡相關(guān)聯(lián)的圖形上下文可以在視頻卡上緩存該層,這使得繪制層中的內(nèi)容比渲染從位圖圖形上下文構(gòu)造的類似圖像快得多。由于這個原因,一個圖層通常是屏幕外繪制比位圖圖形上下文更好的選擇。
所有Quartz繪圖函數(shù)繪制到一個圖形上下文。圖形上下文提供了目標(biāo)的抽象,使您無需了解目標(biāo)的詳細信息,例如其分辨率。您在用戶空間中工作,Quartz執(zhí)行必要的轉(zhuǎn)換以正確地將圖形渲染到目標(biāo)。當(dāng)您使用CGLayer對象進行繪制時,還會繪制到圖形上下文。圖12-1說明了圖層繪制的必要步驟。
所有圖層繪圖都從一個圖形上下文開始,從中使用函數(shù)CGLayerCreateWithContext創(chuàng)建一個CGLayer對象。用于創(chuàng)建CGLayer對象的圖形上下文通常是窗口圖形上下文。 Quartz創(chuàng)建一個圖層,使其具有圖形上下文的所有特征 - 其分辨率,顏色空間和圖形狀態(tài)設(shè)置。如果不想使用圖形上下文的大小,可以為圖層提供大小。在圖12-2中,左側(cè)顯示了用于創(chuàng)建圖層的圖形上下文。右側(cè)框中的灰色部分,標(biāo)記為CGLayer對象,表示新創(chuàng)建的圖層。
在您可以繪制到圖層之前,必須通過調(diào)用函數(shù)CGLayerGetContext來獲取與圖層相關(guān)聯(lián)的圖形上下文。此圖形上下文與用于創(chuàng)建圖層的圖形上下文具有相同的風(fēng)格。只要用于創(chuàng)建圖層的圖形上下文是一個窗口圖形上下文,那么CGLayer圖形上下文將被緩存到GPU,如果可能的話。圖12-2右側(cè)的框的白色部分表示新創(chuàng)建的層圖形上下文。
您可以繪制到圖層的圖形上下文,就像繪制任何圖形上下文,將圖層的圖形上下文傳遞到繪圖功能。圖12-2顯示了繪制到圖層上下文的葉形。
當(dāng)你準(zhǔn)備好使用圖層的內(nèi)容,你可以調(diào)用函數(shù)CGContextDrawLayerInRect或CGContextDrawLayerAtPoint,將圖層繪制到圖形上下文中。通常,你會繪制到用于創(chuàng)建圖層對象的相同的圖形上下文,但不是必需的。您可以將圖層繪制到任何圖形上下文,請記住,圖層繪圖具有用于創(chuàng)建圖層上下文的特征,這可能會施加某些約束(例如性能或分辨率)。例如,與屏幕相關(guān)聯(lián)的層可以被高速緩存在視頻硬件中。如果目的地上下文是打印或PDF上下文,則可能需要從圖形硬件取回到存儲器,導(dǎo)致差的性能。
圖12-2顯示了圖層的內(nèi)容 - 重復(fù)繪圖到用于創(chuàng)建圖層對象的圖形上下文。在釋放CGLayer對象之前,您可以重復(fù)使用圖層中的繪圖次數(shù)。
小提示:當(dāng)您想要繪制圖形的各個部分以實現(xiàn)像陰影一組對象這樣的效果時,請使用透明度圖層。 (請參閱透明層。)當(dāng)您要繪制屏幕或需要重復(fù)繪制相同的事物時,使用CGLayer對象。
用圖層繪制
您需要執(zhí)行以下部分中描述的任務(wù)以使用CGLayer對象進行繪制:
- 創(chuàng)建使用現(xiàn)有圖形上下文初始化的CGLayer對象
- 為圖層獲取圖形上下文
- 繪制到CGLayer圖形上下文
- 將圖層繪制到目標(biāo)圖形上下文
有關(guān)詳細代碼示例,請參閱示例:使用多個CGLayer對象繪制標(biāo)志。
創(chuàng)建使用現(xiàn)有圖形上下文初始化的CGLayer對象
函數(shù)CGLayerCreateWithContext返回使用現(xiàn)有圖形上下文初始化的圖層。 該圖層繼承了圖形上下文的所有特性,包括顏色空間,大小,分辨率和像素格式。 后來,當(dāng)你將圖層繪制到目的地時,Quartz自動將圖層匹配到目標(biāo)上下文。
函數(shù)CGLayerCreateWithContext有三個參數(shù):
- 從中創(chuàng)建圖層的圖形上下文。 通常,您傳遞一個窗口圖形上下文,以便以后可以在屏幕上繪制圖層。
- 圖層相對于圖形上下文的大小。 該圖層可以與圖形上下文的大小相同或更小。 如果以后需要檢索圖層大小,可以調(diào)用函數(shù)CGLayerGetSize。
- 輔助字典。 此參數(shù)當(dāng)前未使用,因此傳遞NULL。
為圖層獲取圖形上下文
Quartz總是繪制一個圖形上下文。 既然你有一個圖層,你必須創(chuàng)建一個與圖層相關(guān)的圖形上下文。 你繪制到圖層上下文中的任何內(nèi)容都是圖層的一部分。
函數(shù)CGLayerGetContext采用一個圖層作為參數(shù),并返回與圖層相關(guān)的圖形上下文。
繪制到CGLayer圖形上下文
獲取與圖層相關(guān)聯(lián)的圖形上下文后,可以對圖層圖形上下文執(zhí)行任何繪圖。 您可以打開PDF文件或圖像文件,并將文件內(nèi)容繪制到圖層。 您可以使用任何Quartz 2D函數(shù)來繪制矩形,線條和其他繪圖圖元。 圖12-3顯示了將矩形和線繪制到圖層的示例。
例如,要將填充矩形繪制到CGLayer圖形上下文,您可以調(diào)用函數(shù)CGContextFillRect,提供從函數(shù)CGLayerGetContext獲取的圖形上下文。 如果圖形上下文命名為myLayerContext,則函數(shù)調(diào)用如下所示:
CGContextFillRect(myLayerContext,myRect)
將圖層繪制到目標(biāo)圖形上下文
當(dāng)您準(zhǔn)備好將圖層繪制到其目標(biāo)圖形上下文時,可以使用以下任一函數(shù):
- CGContextDrawLayerInRect,它在指定的矩形中將圖層繪制到圖形上下文。
- CGContextDrawLayerAtPoint,它在指定的點將圖層繪制到圖形上下文。
通常,您提供的目標(biāo)圖形上下文是一個窗口圖形上下文,它與您用于創(chuàng)建圖層的圖形上下文相同。 圖12-4顯示了重復(fù)繪制圖12-3所示圖層的結(jié)果。 要實現(xiàn)圖案效果,您可以重復(fù)調(diào)用任一圖層繪制函數(shù) - CGContextDrawLayerAtPoint或CGContextDrawLayerInRect - 每次更改偏移量。 例如,您可以調(diào)用函數(shù)CGContextTranslateCTM來更改每次繪制圖層時坐標(biāo)空間的原點。
提示:您不需要將圖層繪制到用于初始化圖層的相同圖形上下文。 但是,如果將圖層繪制到另一個圖形上下文,原始圖形上下文的任何限制都會強加在您的圖形上。
示例:使用多個CGLayer對象來繪制國旗
本節(jié)說明如何使用兩個CGLayer對象來繪制屏幕上圖12-5所示的標(biāo)志。 首先,你將看到如何將標(biāo)志減少到簡單的繪圖基元,然后你將看到完成繪圖所需的代碼。
從在屏幕上繪制的角度來看,該標(biāo)志具有三個部分:
- 紅色和白色條紋的圖案。您可以將圖案縮小為單個紅色條紋,因為在屏幕上繪制時,可以假設(shè)為白色背景。您創(chuàng)建一個單一的紅色矩形,然后重復(fù)繪制矩形在各種偏移量,以創(chuàng)建美國國旗必要的七條紅色條紋。層是重復(fù)繪圖的理想選擇。您將紅色矩形繪制到圖層,然后在屏幕上繪制七次。
- 一個藍色矩形。你需要一個藍色的矩形,所以使用一個層是沒有什么好處。當(dāng)?shù)搅死L制藍色矩形的時候,直接在屏幕上繪制。
- 50個白色星的圖案。像紅色條紋,一層是理想的繪制的星星。您創(chuàng)建 一個概述星形形狀的路徑,然后用白色填充路徑。繪制一個星星到一個圖層,然后繪制圖層50次,每次調(diào)整偏移量以獲得適當(dāng)?shù)拈g距。
圖12-2中的代碼生成如圖12-5所示的輸出。每個編號的代碼行的詳細說明顯示在列表之后。列表是相當(dāng)長的,所以你可能想打印的解釋,以便你可以看看你看代碼。 myDrawFlag例程從Cocoa應(yīng)用程序中調(diào)用。應(yīng)用程序傳遞窗口圖形上下文和指定與窗口圖形上下文相關(guān)聯(lián)的視圖大小的矩形。
注:在調(diào)用此或任何使用CGLayer對象的例程之前,必須檢查以確保系統(tǒng)正在運行Mac OS X v10.4或更高版本,并且具有支持使用CGLayer對象的圖形卡。
// 使用圖層繪制國旗的代碼
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
}
這里是代碼做了什么:
- 聲明第一個星的水平位置的變量。
- 聲明第一個星的垂直位置的變量。
- 聲明標(biāo)志上紅色條紋之間的間距的變量。
- 聲明一個變量的標(biāo)志上的星星之間的水平間距。
- 聲明一個變量的標(biāo)志上的星星之間的垂直間距。
- 聲明指定在哪里繪制標(biāo)志(邊界框),條紋圖層和星形字段的矩形。
- 聲明一個點數(shù)組,指定描繪一個星的線。
- 創(chuàng)建一個是單個條帶形狀的矩形。
- 創(chuàng)建一個為星形字段形狀的矩形。
- 創(chuàng)建一個與傳遞給myDrawFlag例程的窗口圖形上下文大小相同的邊界框。
- 創(chuàng)建一個使用傳遞給myDrawFlag例程的窗口圖形上下文初始化的圖層。
- 獲取與該圖層相關(guān)聯(lián)的圖形上下文。您將使用此圖層進行條帶繪圖。
- 將與條紋圖層關(guān)聯(lián)的圖形上下文的填充顏色設(shè)置為不透明紅色。
- 填充代表一個紅色條紋的矩形。
- 創(chuàng)建另一個層,該層使用傳遞給myDrawFlag例程的窗口圖形上下文初始化。
- 獲取與該圖層相關(guān)聯(lián)的圖形上下文。您將使用此圖層作為星形繪圖。
- 將與星形圖層關(guān)聯(lián)的圖形上下文的填充顏色設(shè)置為不透明白色。
- 將由myStarPoints數(shù)組定義的10行添加到與星形圖層相關(guān)聯(lián)的上下文中。
- 填充路徑,其中包含剛剛添加的10行。
- 保存Windows圖形上下文的圖形狀態(tài)。你需要這樣做,因為你會反復(fù)繪制相同的條紋,但在不同的位置。
- 設(shè)置一個迭代7次的循環(huán),每次對標(biāo)志上的每個紅色條帶。
- 繪制條紋圖層(由一條紅色條紋組成)。
- 翻轉(zhuǎn)當(dāng)前變換矩陣,使原點位于必須繪制下一個紅色條紋的位置。
- 將圖形狀態(tài)恢復(fù)為繪制條紋之前的狀態(tài)。
- 將填充顏色設(shè)置為星形字段的適當(dāng)藍色陰影。請注意,此顏色的透明度為1.0。雖然這個例子中的所有顏色都是不透明的,但它們不需要是。通過使用部分透明的顏色,您可以使用分層繪圖創(chuàng)建漂亮的效果。回想一下,alpha值為0.0指定透明顏色。
- 用藍色填充星形字段矩形。將此矩形直接繪制到窗口圖形上下文。如果你只畫一次,不要使用圖層。
- 保存窗口圖形上下文的圖形狀態(tài),因為您將轉(zhuǎn)換CTM以正確定位星星。
- 翻轉(zhuǎn)CTM,使原點位于星形字段中,為第一個(下)行中的第一個星(左側(cè))定位。
- 這和下一個for循環(huán)設(shè)置代碼重復(fù)繪制星形圖層,所以標(biāo)志上的五個奇數(shù)行包含六顆星。
- 將星形圖層繪制到窗口圖形上下文。回想一下,星形圖層包含一個白色星形。
- 定位CTM,使原點向右移動,準(zhǔn)備繪制下一個星。
- 定位CTM,使原點向上移動,準(zhǔn)備繪制下一行星。
- 翻轉(zhuǎn)CTM,使原點位于星形字段中,為從底部起的第二行中的第一個星(左側(cè))定位。注意,偶數(shù)行相對于奇數(shù)行偏移。
- 這和下一個for循環(huán)設(shè)置代碼重復(fù)繪制星形圖層,所以標(biāo)志上的四個偶數(shù)行都包含五顆星。
- 將星形圖層繪制到窗口圖形上下文。
- 定位CTM,使原點向右移動,準(zhǔn)備繪制下一個星。
- 將CTM定位,使原點向下,向左移動,以準(zhǔn)備繪制下一行星。
- 釋放條帶層。
- 釋放星形圖層