當前位置:
首頁 > 最新 > Core Graphics,第二部分:說說 context

Core Graphics,第二部分:說說 context

context (上下文)就是 Quartz 的核心:你需要按照某種規範來與當前的 Core Graphics context 交互以真正繪製東西,因此熟悉它、它做什麼以及為什麼它是這樣的是有益處的。

Core Graphics 裡面一個基礎的操作是創建一個 path。Path 是形狀的數學描述。一個 path 可以是一個矩形,或一個圓、一個牛仔帽,或者甚至是泰姬陵。Path 可以用顏色填充——就是說,這個 path 中的所有的點都被設置成特定的顏色。Path 也可以畫出輪廓(outlined),或者說叫描邊(stroked)。這就像是用一支美術鋼筆在路徑周圍畫出一個輪廓。下面分別是一個只畫出了輪廓的、一個只填充顏色的和一個既填充了黃色由描藍邊的帽子:

你可以看到,實際的輪廓可以變得非常複雜。它可以是一種特定的顏色。(輪廓)線也可以有虛線圖案。可以用粗線條描邊也可以用細線。線的末端可以是方的或圓的,等等等等。有很多種屬性。

如果你仔細研讀 Core Graphics API,你並不會看到某個方法調用使用了所有的這些設置:

CGStrokePath (path, fillColor, strokeColor, lineWidth, dashPattern, bloodType, endCap)

相反,僅僅是這樣:

void CGContextStrokePath(CGContextRef c)

那,那些額外的值從哪兒來的?它們就從 context 中來。

一桶零碎

Context 維持著一堆關於繪製的全局狀態,它們是一堆獨立的值:

current path

current fill 和 stroke colors

line width 和 pattern

line cap 和 join (miter) styles

alpha (transparency), antialiasing 和 blend mode

shadows

transformation matrix

text atrributes (文字屬性) (font, size, matrix)

一些冷僻的東西比如 line flatness 和 interpolation quality

以及更多

有很多狀態量。Core Graphics 維持的狀態量的全集並沒有被寫入文檔,因此可能還有更多的設置項。不同種類的 context (比如,圖片與 PDF)可能包含額外種類的數據。

不管什麼時候當 Core Graphics 被告知要繪製什麼東西時,比如「填充一條路徑(path),」它都從當前的 context 中去找需要的那部分數據。根據 context 中包含什麼,同樣的一個代碼序列可以有完全不同的結果。一方面,這很強大。一段泛型的繪製代碼可以通過 context 改變得到不同的結果。另一方面,context 是一大堆全局狀態,而全局狀態很容易被無意中搞得亂七八糟。

比如說有這麼一段代碼:

draw orange square: set color to orange in the current context fill a rectangle

你將得到一個橙色正方形。現在假設你還要繪製一個桃心:

draw red valentine: set color to red in the current context fill a valentine

耶!一個紅心。現在比如說你把畫桃心的代碼加到你的第一個方法里:

draw orange square: set color to orange in the current context draw red valentine fill a rectangle

你的矩形會是紅色而不是橙色。為什麼呢?繪製桃心的代碼搶佔了當前的繪製顏色。你填充矩形的時候那個顏色本來是橙色,但是現在是紅的了。如何避免這樣的 bug 呢?

有兩種方式。一種是在改變狀態之前將狀態保存起來——如果你要改變全局顏色,保存現在的顏色,改變顏色,繪製,然後恢復之前的顏色。這樣只有一兩個參數的時候還行,但是如果你要改變很多的時候這個方法並不能擴大規模。還有一些設置項因為一些副作用被改變,因此你也得考慮它們。噢,然後其實在 Core Graphics 里是沒法這麼做的,因為根本沒有當前 context 的 getter。抱歉咯。

這些桶的棧(context 棧)

另外一種方式是在改變任何東西前保存完整的 context。保存 context,改變顏色或者線寬,繪製,然後恢復完整的 context。Core Graphics API 提供了保存和恢復當前 context 設置的方法。這些設置叫做 graphics state,或者是 GState。事實上,它在背後維持著一個 GStates 棧。

當你保存了當前 context 的設置,它們被壓入一個棧中。每一個 context 都有一個棧。當你恢復 graphics state,之前保存的 GState 從棧中彈出來並且編程 context 當前的值。將桃心繪製代碼這樣修改可以修復「橙色矩形是紅色」的 bug:

draw red valentine: save graphics state set color to red in the current context fill a valentine restore graphics state

然後。完整的繪製調用序列是這個樣子的:

set color to orange in the current context save graphics state set color to red in the current context fill a valentine restore graphics state fill a rectangle

下面是 GState 的改變:

Core Graphics API

好了,在抽象層面還行,但是這些東西在你實際看到它時是什麼樣呢?並不完全如你所想。Core Graphics 是一個 Core Foundation 味道的 API。有很多 Core Foundation 的傳統影響著 Core Graphics。最主要的古怪點在於 Core Foundation 對於用指針聲明東西有一種莫名其妙的恐懼。結果就是用 Objective-C 中的 「Ref」 類型,比如 或者 。這些其實是類型重定義之後隱藏了那顆星的指針。

以下是正確的:

CGContextRef currentContext = ....; // 實際上是個指針

以下不正確:

CGContextRef *currentContext = ...; // 指向指針的指針

你的繪製代碼很少會創建它在其中繪製的 context,而是使用當前 context。你可以在 iOS 中這樣獲取當前 context:

CGContextRef context = UIGraphicsGetCurrentContext ();

在 Desktop Cocoa,OS X 10.10 之前,用:

CGContextRef context = [NSGraphicsContext.currentContext graphicsPort]

在 10.10 之後:

CGContextRef context = [NSGraphicsContext.currentContext CGContext]畫啊,朋友!

因為 CG API 是一個面對對象的 C API,方法都是根據它們所操作的「對象」命名的(比如, 或者 ),並且方法的第一個參數如同 Objective-C 中的 reveiver。因此就是那個「對象」被這些調用改變。

例如,下面是一個畫矩形輪廓的 CGContext 調用:

CGContextRef context = ...; // 參照上方對應平台的調用 CGRect bounds = someView.bounds; CGContextStrokeRect (context, bounds);

喜歡這篇文章嗎?立刻分享出去讓更多人知道吧!

本站內容充實豐富,博大精深,小編精選每日熱門資訊,隨時更新,點擊「搶先收到最新資訊」瀏覽吧!


請您繼續閱讀更多來自 推酷 的精彩文章:

對P10的洗白,終於徹底摘掉了zealer「客觀、獨立、第三方」的帽子
為什麼我們當初沒有選擇 Kotlin
增強網站設計吸引力的方法
log4j 日誌信息的引入——解決項目運行過程中的日誌信息
React Native+Cordova WebView 演進:Plugin 篇

TAG:推酷 |

您可能感興趣

Jack Ma:Core technology capability is more important than market value
《The Balanced Scorecard》,作者:R.Kaplan,D.Norton
win10 uwp教你使用 asp dotnet core 做 cs 程序
adidas Y-3 Harigane 「Core Black」亮眼登場
今春穿搭:Normcore&Atheleisure
adidas Yeezy Powerphase 『Core Black』全黑配色17號發售
發售通知 adidas Originals YEEZY Powerphase「Core Black」
微軟Azure Spatial Anchors開始支持HoloLens 2和ARCore 1.7
在fate中不一樣設定的動漫,Fate/Extra Last Encore!
dotnet core webapi+vue 搭建前後端完全分離web架構(一)
Entity Framework Core 2.0 入門
HyperX Cloud Alpha拆解和Core/Silver綜評
全黑 Yeezy Powerphase 「Core Black」 將在本月發售
#新勢力發售#Yeezy PowerPhase 「Core Black」| Xsneaker
Adidas Original POD-S3.1 「Core Black」
ARCore App已改名為Google Play Services for AR
帶你看看珠寶廠加工的耳塞——美國NOBLE Kaiser Encore & Brass Limited
取代intel Core架構曝光:Ocean Cove 12代產品?
Kobe戰靴再次出新!adidas Crazy 1 ADV Core Black登場!
Coreldraw X8 64bit