架構(gòu)

(引用作者框架對比圖片)
YYText包括控件(YYLabel,YYTextView),布局(YYTextLayout,NSAttributedString,YYTextContainer),核心(CoreText)。
源碼目錄組織

YYLabel
繼承關(guān)系

YYLabel 直接繼承 UIView,作者自己實(shí)現(xiàn) Label 的渲染。+_+
state
struct {
// 是否需要更新布局
unsigned int layoutNeedUpdate : 1;
unsigned int showingHighlight : 1;
unsigned int trackingTouch : 1;
unsigned int swallowTouch : 1;
unsigned int touchMoved : 1;
unsigned int hasTapAction : 1;
unsigned int hasLongPressAction : 1;
// 內(nèi)容是否支持逐漸消失
unsigned int contentsNeedFade : 1;
} _state;
如何熏染出 Text
YYLabel 的熏染是通過 YYTextAsyncLayerDelegate 完成。 YYTextAsyncLayerDelegate 提供了 newAsyncDisplayTask 配置方法用來實(shí)現(xiàn)渲染。
YYTextAsyncLayer 與 YYLabel 的熏染流程
已 setText 為例,看看這個(gè)熏染的流程。

-
[self.layer setNeedsDisplay]這里調(diào)用的是YYTextAsyncLayer的setNeedsDisplay。因?yàn)?layerClass方法被重寫了,返回了YYTextAsyncLayer。所以主layer所使用的類是YYTextAsyncLayer。 -
_cancelAsyncDisplay的實(shí)現(xiàn),后續(xù)再探討。。。記遺留問題。 - 這里
display也被重寫了,在這了執(zhí)行了渲染最為關(guān)鍵的函數(shù)_displayAsync。 -
YYTextAsyncLayer提供了displaysAsynchronously用來控制是否進(jìn)行異步渲染,默認(rèn)為異步熏染。
熏染
本人對 Core Graphics Framework 部分不同熟悉,個(gè)人重點(diǎn)對這一塊代碼進(jìn)行學(xué)。剛才我們發(fā)現(xiàn)這里的渲染分為:普通渲染(ps:不知道怎么稱,叫同步渲染感覺不太適合,就叫普通渲染吧)和異步渲染。這兩種渲染的渲染代碼處理基本是一樣的,只是異步熏染增加了一些多線程的處理的考慮(比如:多線程經(jīng)典的“讀與寫”的問題)。
所以就直接學(xué)習(xí)普通渲染部分的代碼吧#^_^#
YYTextAsyncLayer 熏染學(xué)習(xí)
UIGraphicsBeginImageContextWithOptions(self.bounds.size, self.opaque, self.contentsScale);
CGContextRef context = UIGraphicsGetCurrentContext();
if (self.opaque) {
CGSize size = self.bounds.size;
size.width *= self.contentsScale;
size.height *= self.contentsScale;
CGContextSaveGState(context); {
if (!self.backgroundColor || CGColorGetAlpha(self.backgroundColor) < 1) {
CGContextSetFillColorWithColor(context, [UIColor whiteColor].CGColor);
CGContextAddRect(context, CGRectMake(0, 0, size.width, size.height));
CGContextFillPath(context);
}
if (self.backgroundColor) {
CGContextSetFillColorWithColor(context, self.backgroundColor);
CGContextAddRect(context, CGRectMake(0, 0, size.width, size.height));
CGContextFillPath(context);
}
} CGContextRestoreGState(context);
}
task.display(context, self.bounds.size, ^{return NO;});
UIImage *image = UIGraphicsGetImageFromCurrentImageContext();
UIGraphicsEndImageContext();
self.contents = (__bridge id)(image.CGImage);
- 開始是調(diào)用
UIGraphicsBeginImageContextWithOptions創(chuàng)建一個(gè)圖片處理的上下文。 繪制結(jié)束調(diào)用UIGraphicsEndImageContext。 - 通過
UIGraphicsGetCurrentContext獲取當(dāng)前圖形的上下文。 - 這里有個(gè)
opaque屬性表示是否不透明,詳細(xì)屬性參見。 -
CGContextSaveGState把上下文保存到棧中。然后通過CGContextSetFillColorWithColor設(shè)置填充顏色,CGContextAddRect添加矩形,CGContextFillPath填充上下文路徑。 最后保存通過CGContextRestoreGState保存最近的上下文。 - 調(diào)用
task.display回調(diào),這里是調(diào)用配置的渲染方法,后面再分析YYLabel的熏染回調(diào)。YYLabel的熏染主要通過YYTextLayout來處理。 這么后續(xù)再做學(xué)習(xí)。 - 通過
UIGraphicsGetImageFromCurrentImageContext當(dāng)前的上下文繪制出來的圖片,結(jié)束繪制。 - 最后將圖片賦值給
contents屬性完成熏染。