從iOS的圖片圓角想到渲染

圓角是一種很常見(jiàn)的視圖效果属提,相比于直角,它更加柔和優(yōu)美病往,易于接受捣染。設(shè)置圓角會(huì)帶來(lái)一定的性能損耗,如何提高性能是一個(gè)需要重點(diǎn)討論的話題停巷。

大家常見(jiàn)的圓角代碼x.layer.cornerRadius = xx; x.clipsToBounds = YES;這兩行確實(shí)實(shí)現(xiàn)了圓角視覺(jué)效果耍攘。其實(shí)使用x.layer.cornerRadius = xx;已經(jīng)實(shí)現(xiàn)了圓角,只不過(guò)在某些控件是不生效的畔勤,因?yàn)槟承﹫D層在被切割圓角圖層之上而被顯示出來(lái)了蕾各。而x.clipsToBounds = YES;帶來(lái)的后果就是產(chǎn)生離屏渲染∏炀荆可以使用instruments中的CoreAnimation工具式曲,打開(kāi)Color Offscren-Rednered Yellow選項(xiàng),可見(jiàn)黃色區(qū)域部分即是離屏渲染部分缸榛。

那么離屏渲染會(huì)帶來(lái)什么吝羞?當(dāng)然后資源損耗,可能產(chǎn)生卡頓内颗。因?yàn)樵趇Phone設(shè)備的硬件資源有差異钧排,當(dāng)離屏渲染不多時(shí),并不是很明顯感覺(jué)到它的缺點(diǎn)均澳。

文章中說(shuō)到的具體源碼可以轉(zhuǎn)至github進(jìn)行star DDCornerRadius 歡迎issue卖氨。

什么是像素

像素会烙,為視頻顯示的基本單位,譯自英文“pixel”筒捺,pix是英語(yǔ)單詞picture的常用簡(jiǎn)寫(xiě)柏腻,加上英語(yǔ)單詞“元素”element,就得到pixel系吭,故“像素”表示“畫(huà)像元素”之意五嫂,有時(shí)亦被稱(chēng)為pel(picture element)。每個(gè)這樣的消息元素不是一個(gè)點(diǎn)或者一個(gè)方塊肯尺,而是一個(gè)抽象的取樣沃缘。像素是由紅,綠则吟,藍(lán)三種顏色組件構(gòu)成的槐臀。因此,位圖數(shù)據(jù)有時(shí)也被叫做 RGB 數(shù)據(jù)氓仲。

顯示機(jī)制

一個(gè)像素是如何繪制到屏幕上去的水慨?有很多種方式將一些東西映射到顯示屏上,他們需要調(diào)用不同的框架敬扛、許多功能和方法的結(jié)合體晰洒。這里我們大概看一下屏幕之后發(fā)生的事情。

圖像想顯示到屏幕上使人肉眼可見(jiàn)都需借助像素的力量啥箭。它們密集的排布在手機(jī)屏幕上谍珊,將任何圖形通過(guò)不同的色值表現(xiàn)出來(lái)。計(jì)算機(jī)顯示的流程大致可以描述為將圖像轉(zhuǎn)化為一系列像素點(diǎn)的排列然后打印在屏幕上急侥,由圖像轉(zhuǎn)化為像素點(diǎn)的過(guò)程又可以稱(chēng)之為光柵化砌滞,就是從矢量的點(diǎn)線面的描述,變成像素的描述坏怪。

display screen

回溯歷史布持,可以從過(guò)去的 CRT 顯示器原理說(shuō)起。CRT 的電子槍按照上面方式陕悬,從上到下一行行掃描题暖,掃描完成后顯示器就呈現(xiàn)一幀畫(huà)面,隨后電子槍回到初始位置繼續(xù)下一次掃描捉超。為了把顯示器的顯示過(guò)程和系統(tǒng)的視頻控制器進(jìn)行同步胧卤,顯示器(或者其他硬件)會(huì)用硬件時(shí)鐘產(chǎn)生一系列的定時(shí)信號(hào)。當(dāng)電子槍換到新的一行拼岳,準(zhǔn)備進(jìn)行掃描時(shí)枝誊,顯示器會(huì)發(fā)出一個(gè)水平同步信號(hào)(horizonal synchronization),簡(jiǎn)稱(chēng) HSync惜纸;而當(dāng)一幀畫(huà)面繪制完成后叶撒,電子槍回復(fù)到原位绝骚,準(zhǔn)備畫(huà)下一幀前,顯示器會(huì)發(fā)出一個(gè)垂直同步信號(hào)(vertical synchronization)祠够,簡(jiǎn)稱(chēng) VSync压汪。顯示器通常以固定頻率進(jìn)行刷新,這個(gè)刷新率就是 VSync 信號(hào)產(chǎn)生的頻率古瓤。盡管現(xiàn)在的設(shè)備大都是液晶顯示屏了止剖,但原理仍然沒(méi)有變。

關(guān)于卡頓的簡(jiǎn)單原理解釋

在 VSync 信號(hào)到來(lái)后落君,系統(tǒng)圖形服務(wù)會(huì)通過(guò) CADisplayLink 等機(jī)制通知 App穿香,App 主線程開(kāi)始在 CPU 中計(jì)算顯示內(nèi)容,比如視圖的創(chuàng)建绎速、布局計(jì)算皮获、圖片解碼、文本繪制等纹冤。隨后 CPU 會(huì)將計(jì)算好的內(nèi)容提交到 GPU 去洒宝,由 GPU 進(jìn)行變換、合成赵哲、渲染。隨后 GPU 會(huì)把渲染結(jié)果提交到幀緩沖區(qū)去君丁,等待下一次 VSync 信號(hào)到來(lái)時(shí)顯示到屏幕上枫夺。由于垂直同步的機(jī)制,如果在一個(gè) VSync 時(shí)間內(nèi)绘闷,CPU 或者 GPU 沒(méi)有完成內(nèi)容提交橡庞,則那一幀就會(huì)被丟棄,等待下一次機(jī)會(huì)再顯示印蔗,而這時(shí)顯示屏?xí)A糁暗膬?nèi)容不變扒最。這就是界面卡頓的原因。

CPU 和 GPU 不論哪個(gè)阻礙了顯示流程华嘹,都會(huì)造成掉幀現(xiàn)象吧趣。所以開(kāi)發(fā)時(shí),也需要分別對(duì) CPU 和 GPU 壓力進(jìn)行評(píng)估和優(yōu)化耙厚。

渲染機(jī)制

當(dāng)像素映射到屏幕上的時(shí)候强挫,后臺(tái)發(fā)生了很多事情。但一旦它們顯示到屏幕上薛躬,每一個(gè)像素均由三個(gè)顏色組件構(gòu)成:紅俯渤,綠,藍(lán)型宝。三個(gè)獨(dú)立的顏色單元會(huì)根據(jù)給定的顏色顯示到一個(gè)像素上八匠。在 iPhoneSE 的顯示器上有1,136×640=727,040個(gè)像素絮爷,因此有2,181,120個(gè)顏色單元。在一些Retina屏幕上梨树,這一數(shù)字將達(dá)到百萬(wàn)以上坑夯。所有的圖形堆棧一起工作以確保每次正確的顯示。當(dāng)你滾動(dòng)整個(gè)屏幕的時(shí)候劝萤,數(shù)以百萬(wàn)計(jì)的顏色單元必須以每秒60次的速度刷新渊涝,這就是一個(gè)很大的工作量。

簡(jiǎn)單來(lái)說(shuō)床嫌,iOS的顯示機(jī)制大致如此:


pixels software stack

Display 的上一層便是圖形處理單元 GPU跨释,GPU 是一個(gè)專(zhuān)門(mén)為圖形高并發(fā)計(jì)算而量身定做的處理單元。這也是為什么它能同時(shí)更新所有的像素厌处,并呈現(xiàn)到顯示器上鳖谈。它的并發(fā)本性讓它能高效的將不同紋理合成起來(lái)。所以阔涉,開(kāi)發(fā)中我們應(yīng)該盡量讓CPU負(fù)責(zé)主線程的UI調(diào)動(dòng)缆娃,把圖形顯示相關(guān)的工作交給GPU來(lái)處理。

GPU Driver 是直接和 GPU 交流的代碼塊瑰排。不同的GPU是不同的性能怪獸贯要,但是驅(qū)動(dòng)使它們?cè)谙乱粋€(gè)層級(jí)上顯示的更為統(tǒng)一,典型的下一層級(jí)有 OpenGL/OpenGL ES.

OpenGL(Open Graphics Library) 是一個(gè)提供了 2D 和 3D 圖形渲染的 API椭住。GPU 是一塊非常特殊的硬件崇渗,OpenGL 和 GPU 密切的工作以提高GPU的能力,并實(shí)現(xiàn)硬件加速渲染京郑。

OpenGL 之上擴(kuò)展出很多東西宅广。在 iOS 上,幾乎所有的東西都是通過(guò) Core Animation 繪制出來(lái)些举,然而在 OS X 上跟狱,繞過(guò) Core Animation 直接使用 Core Graphics 繪制的情況并不少見(jiàn)。對(duì)于一些專(zhuān)門(mén)的應(yīng)用户魏,尤其是游戲驶臊,程序可能直接和 OpenGL/OpenGL ES 交流。

需要強(qiáng)調(diào)的是叼丑,GPU 是一個(gè)非常強(qiáng)大的圖形硬件资铡,并且在顯示像素方面起著核心作用。它連接到 CPU幢码。從硬件上講兩者之間存在某種類(lèi)型的總線笤休,并且有像 OpenGL,Core Animation 和 Core Graphics 這樣的框架來(lái)在 GPU 和 CPU 之間精心安排數(shù)據(jù)的傳輸症副。為了將像素顯示到屏幕上店雅,一些處理將在 CPU 上進(jìn)行政基。然后數(shù)據(jù)將會(huì)傳送到 GPU,最終像素顯示到屏幕上闹啦。

pixels hardware

正如上圖顯示沮明,GPU 需要將每一個(gè) frame 的紋理(位圖)合成在一起(一秒60次)。每一個(gè)紋理會(huì)占用 VRAM(video RAM)窍奋,所以需要給 GPU 同時(shí)保持紋理的數(shù)量做一個(gè)限制荐健。GPU 在合成方面非常高效,但是某些合成任務(wù)卻比其他更復(fù)雜琳袄,并且 GPU在 16.7ms(1/60s)內(nèi)能做的工作也是有限的江场。

另外一個(gè)問(wèn)題就是將數(shù)據(jù)傳輸?shù)?GPU 上。為了讓 GPU 訪問(wèn)數(shù)據(jù)窖逗,需要將數(shù)據(jù)從 RAM 移動(dòng)到 VRAM 上址否。這就是提及到的上傳數(shù)據(jù)到 GPU。這些看起來(lái)貌似微不足道碎紊,但是一些大型的紋理卻會(huì)非常耗時(shí)佑附。

最終,CPU 開(kāi)始運(yùn)行程序仗考。你可能會(huì)讓 CPU 從 bundle 加載一張 PNG 的圖片并且解壓它音同。這所有的事情都在 CPU 上進(jìn)行。然后當(dāng)你需要顯示解壓縮后的圖片時(shí)秃嗜,它需要以某種方式上傳到 GPU权均。一些看似平凡的,比如顯示文本痪寻,對(duì) CPU 來(lái)說(shuō)卻是一件非常復(fù)雜的事情螺句,這會(huì)促使 Core Text 和 Core Graphics 框架更緊密的集成來(lái)根據(jù)文本生成一個(gè)位圖虽惭。一旦準(zhǔn)備好橡类,它將會(huì)被作為一個(gè)紋理上傳到 GPU 并準(zhǔn)備顯示出來(lái)。當(dāng)你滾動(dòng)或者在屏幕上移動(dòng)文本時(shí)芽唇,同樣的紋理能夠被復(fù)用顾画,CPU 只需簡(jiǎn)單的告訴 GPU 新的位置就行了,所以 GPU 就可以重用存在的紋理了。CPU 并不需要重新渲染文本匆笤,并且位圖也不需要重新上傳到 GPU研侣。

在圖形世界中,合成是一個(gè)描述不同位圖如何放到一起來(lái)創(chuàng)建你最終在屏幕上看到圖像的過(guò)程炮捧。屏幕上一切事物皆紋理庶诡。一個(gè)紋理就是一個(gè)包含 RGBA 值的長(zhǎng)方形,比如咆课,每一個(gè)像素里面都包含紅末誓、綠扯俱、藍(lán)和透明度的值。在 Core Animation 世界中這就相當(dāng)于一個(gè) CALayer喇澡。

每一個(gè) layer 是一個(gè)紋理迅栅,所有的紋理都以某種方式堆疊在彼此的頂部。對(duì)于屏幕上的每一個(gè)像素晴玖,GPU 需要算出怎么混合這些紋理來(lái)得到像素 RGB 的值读存。這就是合成。

如果我們所擁有的是一個(gè)和屏幕大小一樣并且和屏幕像素對(duì)齊的單一紋理呕屎,那么屏幕上每一個(gè)像素相當(dāng)于紋理中的一個(gè)像素让簿,紋理的最后一個(gè)像素也就是屏幕的最后一個(gè)像素。

如果我們有第二個(gè)紋理放在第一個(gè)紋理之上榨惰,然后GPU將會(huì)把第二個(gè)紋理合成到第一個(gè)紋理中拜英。有很多種不同的合成方法,但是如果我們假定兩個(gè)紋理的像素對(duì)齊琅催,并且使用正常的混合模式居凶,我們便可以用公式來(lái)計(jì)算每一個(gè)像素:R = S + D * ( 1 – Sa )
結(jié)果的顏色是源色彩(頂端紋理)+目標(biāo)顏色(低一層的紋理)*(1-源顏色的透明度)。在這個(gè)公式中所有的顏色都假定已經(jīng)預(yù)先乘以了它們的透明度藤抡。

接著我們進(jìn)行第二個(gè)假定侠碧,兩個(gè)紋理都完全不透明,比如 alpha=1缠黍。如果目標(biāo)紋理(低一層的紋理)是藍(lán)色(RGB=0,0,1)弄兜,并且源紋理(頂層的紋理)顏色是紅色(RGB=1,0,0),因?yàn)?Sa 為1瓷式,所以結(jié)果為:R = S
結(jié)果是源顏色的紅色替饿。這正是我們所期待的(紅色覆蓋了藍(lán)色)。如果源顏色層為50%的透明贸典,比如 alpha=0.5视卢,既然 alpha 組成部分需要預(yù)先乘進(jìn) RGB 的值中,那么 S 的 RGB 值為(0.5, 0, 0)廊驼,公式看起來(lái)便會(huì)像這樣:

                       0.5   0               0.5
R = S + D * (1 - Sa) = 0   + 0 * (1 - 0.5) = 0
                       0     1               0.5

我們最終得到RGB值為(0.5, 0, 0.5),是一個(gè)紫色据过。這正是我們所期望將透明紅色合成到藍(lán)色背景上所得到的。

記住我們剛剛只是將紋理中的一個(gè)像素合成到另一個(gè)紋理的像素上妒挎。當(dāng)兩個(gè)紋理覆蓋在一起的時(shí)候绳锅,GPU需要為所有像素做這種操作。正如你所知道的一樣酝掩,許多程序都有很多層很魂,因此所有的紋理都需要合成到一起致开。盡管GPU是一塊高度優(yōu)化的硬件來(lái)做這種事情丹弱,但這還是會(huì)讓它非常忙碌桥胞。

為何圖片縮放會(huì)增加GPU工作量

當(dāng)所有的像素是對(duì)齊的時(shí)候我們得到相對(duì)簡(jiǎn)單的計(jì)算公式。每當(dāng) GPU 需要計(jì)算出屏幕上一個(gè)像素是什么顏色的時(shí)候,它只需要考慮在這個(gè)像素之上的所有 layer 中對(duì)應(yīng)的單個(gè)像素,并把這些像素合并到一起≈胬或者,如果最頂層的紋理是不透明的(即圖層樹(shù)的最底層)丙笋,這時(shí)候 GPU 就可以簡(jiǎn)單的拷貝它的像素到屏幕上谢澈。

當(dāng)一個(gè) layer 上所有的像素和屏幕上的像素完美的對(duì)應(yīng)整齊,那這個(gè) layer 就是像素對(duì)齊的御板。主要有兩個(gè)原因可能會(huì)造成不對(duì)齊锥忿。第一個(gè)便是滾動(dòng),當(dāng)一個(gè)紋理上下滾動(dòng)的時(shí)候怠肋,紋理的像素便不會(huì)和屏幕的像素排列對(duì)齊敬鬓。另一個(gè)原因便是當(dāng)紋理的起點(diǎn)不在一個(gè)像素的邊界上。

在這兩種情況下笙各,GPU 需要再做額外的計(jì)算钉答。它需要將源紋理上多個(gè)像素混合起來(lái),生成一個(gè)用來(lái)合成的值杈抢。當(dāng)所有的像素都是對(duì)齊的時(shí)候数尿,GPU 只剩下很少的工作要做。

Core Animation 工具和模擬器有一個(gè)Color Misaligned Images選項(xiàng)惶楼,當(dāng)這些在你的 CALayer 實(shí)例中發(fā)生的時(shí)候右蹦,這個(gè)功能便可向你展示。

關(guān)于iOS設(shè)備的一些尺寸限制可以看這里:iOSRes

離屏渲染

On-Screen Rendering意為當(dāng)前屏幕渲染歼捐,指的是GPU的渲染操作是在當(dāng)前用于顯示的屏幕緩沖區(qū)中進(jìn)行何陆。
Off-Screen Rendering意為離屏渲染,指的是GPU在當(dāng)前屏幕緩沖區(qū)以外新開(kāi)辟一個(gè)緩沖區(qū)進(jìn)行渲染操作豹储。

當(dāng)圖層屬性的混合體被指定為在未預(yù)合成之前不能直接在屏幕中繪制時(shí)贷盲,屏幕外渲染就被喚起了。屏幕外渲染并不意味著軟件繪制颂翼,但是它意味著圖層必須在被顯示之前在一個(gè)屏幕外上下文中被渲染(不論CPU還是GPU)晃洒。

離屏渲染可以被 Core Animation 自動(dòng)觸發(fā)慨灭,或者被應(yīng)用程序強(qiáng)制觸發(fā)朦乏。屏幕外的渲染會(huì)合并/渲染圖層樹(shù)的一部分到一個(gè)新的緩沖區(qū),然后該緩沖區(qū)被渲染到屏幕上氧骤。

特殊的“離屏渲染”:CPU渲染

如果我們重寫(xiě)了drawRect方法呻疹,并且使用任何Core Graphics的技術(shù)進(jìn)行了繪制操作,就涉及到了CPU渲染筹陵。
整個(gè)渲染過(guò)程由CPU在App內(nèi)同步地完成刽锤,渲染得到的bitmap最后再交由GPU用于顯示镊尺。

離屏渲染的體現(xiàn)

相比于當(dāng)前屏幕渲染,離屏渲染的代價(jià)是很高的并思,主要體現(xiàn)在兩個(gè)方面:

  • 1 創(chuàng)建新緩沖區(qū)
    要想進(jìn)行離屏渲染庐氮,首先要?jiǎng)?chuàng)建一個(gè)新的緩沖區(qū)。
  • 2 上下文切換
    離屏渲染的整個(gè)過(guò)程宋彼,需要多次切換上下文環(huán)境:先是從當(dāng)前屏幕(On-Screen)切換到離屏(Off-Screen)弄砍;等到離屏渲染結(jié)束以后,將離屏緩沖區(qū)的渲染結(jié)果顯示到屏幕上输涕,又需要將上下文環(huán)境從離屏切換到當(dāng)前屏幕音婶。而上下文環(huán)境的切換是要付出很大代價(jià)的。

觸發(fā)離屏渲染

1莱坎、drawRect
2衣式、layer.shouldRasterize = true;
3、有mask或者是陰影(layer.masksToBounds, layer.shadow*)檐什;
3.1) shouldRasterize(光柵化)
3.2) masks(遮罩)
3.3) shadows(陰影)
3.4) edge antialiasing(抗鋸齒)
3.5) group opacity(不透明)
4碴卧、Text(UILabel, CATextLayer, Core Text, etc)...
注:layer.cornerRadius,layer.borderWidth乃正,layer.borderColor并不會(huì)Offscreen Render螟深,因?yàn)檫@些不需要加入Mask。

圓角優(yōu)化

前面說(shuō)了那么多烫葬,這里就給上實(shí)際可行方案界弧。圓角的優(yōu)化目前考慮兩方面:一是,從圖片入手搭综,將圖片切割成指定圓角樣式垢箕。二是,使用貝塞爾曲線兑巾,利用CALayer層繪制指定圓角樣式的mask遮蓋View条获。

UIImage切割:

UIGraphicsBeginImageContextWithOptions(self.size, NO, 0);
CGContextRef context = UIGraphicsGetCurrentContext();
CGRect rect = CGRectMake(0, 0, self.size.width, self.size.height);
CGContextScaleCTM(context, 1, -1);
CGContextTranslateCTM(context, 0, -rect.size.height);

CGFloat minSize = MIN(self.size.width, self.size.height);
if (borderWidth < minSize / 2.0) {
    UIBezierPath *path = [UIBezierPath bezierPathWithRoundedRect:CGRectInset(rect, borderWidth, borderWidth) byRoundingCorners:corners cornerRadii:CGSizeMake(radius, borderWidth)];
    CGContextSaveGState(context);
    [path addClip];
    CGContextDrawImage(context, rect, self.CGImage);
    CGContextRestoreGState(context);
}

UIImage *image = UIGraphicsGetImageFromCurrentImageContext();
image = [image dd_imageByCornerRadius:radius borderedColor:borderColor borderWidth:borderWidth corners:corners];
UIGraphicsEndImageContext();

圖片繪制:

UIGraphicsBeginImageContextWithOptions(self.size, NO, 0);
[self drawAtPoint:CGPointZero];
CGRect rect = CGRectMake(0, 0, self.size.width, self.size.height);
CGFloat strokeInset = borderWidth / 2.0;
CGRect strokeRect = CGRectInset(rect, strokeInset, strokeInset);
UIBezierPath *path = [UIBezierPath bezierPathWithRoundedRect:strokeRect byRoundingCorners:corners cornerRadii:CGSizeMake(radius, borderWidth)];
path.lineWidth = borderWidth;
[borderColor setStroke];
[path stroke];
UIImage *result = UIGraphicsGetImageFromCurrentImageContext();
UIGraphicsEndImageContext();
最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
  • 序言:七十年代末,一起剝皮案震驚了整個(gè)濱河市蒋歌,隨后出現(xiàn)的幾起案子帅掘,更是在濱河造成了極大的恐慌,老刑警劉巖堂油,帶你破解...
    沈念sama閱讀 211,743評(píng)論 6 492
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件修档,死亡現(xiàn)場(chǎng)離奇詭異,居然都是意外死亡府框,警方通過(guò)查閱死者的電腦和手機(jī)吱窝,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 90,296評(píng)論 3 385
  • 文/潘曉璐 我一進(jìn)店門(mén),熙熙樓的掌柜王于貴愁眉苦臉地迎上來(lái),“玉大人院峡,你說(shuō)我怎么就攤上這事兴使。” “怎么了照激?”我有些...
    開(kāi)封第一講書(shū)人閱讀 157,285評(píng)論 0 348
  • 文/不壞的土叔 我叫張陵发魄,是天一觀的道長(zhǎng)。 經(jīng)常有香客問(wèn)我俩垃,道長(zhǎng)欠母,這世上最難降的妖魔是什么? 我笑而不...
    開(kāi)封第一講書(shū)人閱讀 56,485評(píng)論 1 283
  • 正文 為了忘掉前任吆寨,我火速辦了婚禮赏淌,結(jié)果婚禮上,老公的妹妹穿的比我還像新娘啄清。我一直安慰自己六水,他們只是感情好,可當(dāng)我...
    茶點(diǎn)故事閱讀 65,581評(píng)論 6 386
  • 文/花漫 我一把揭開(kāi)白布辣卒。 她就那樣靜靜地躺著掷贾,像睡著了一般。 火紅的嫁衣襯著肌膚如雪荣茫。 梳的紋絲不亂的頭發(fā)上想帅,一...
    開(kāi)封第一講書(shū)人閱讀 49,821評(píng)論 1 290
  • 那天,我揣著相機(jī)與錄音啡莉,去河邊找鬼港准。 笑死,一個(gè)胖子當(dāng)著我的面吹牛咧欣,可吹牛的內(nèi)容都是我干的浅缸。 我是一名探鬼主播,決...
    沈念sama閱讀 38,960評(píng)論 3 408
  • 文/蒼蘭香墨 我猛地睜開(kāi)眼魄咕,長(zhǎng)吁一口氣:“原來(lái)是場(chǎng)噩夢(mèng)啊……” “哼衩椒!你這毒婦竟也來(lái)了?” 一聲冷哼從身側(cè)響起哮兰,我...
    開(kāi)封第一講書(shū)人閱讀 37,719評(píng)論 0 266
  • 序言:老撾萬(wàn)榮一對(duì)情侶失蹤毛萌,失蹤者是張志新(化名)和其女友劉穎,沒(méi)想到半個(gè)月后喝滞,有當(dāng)?shù)厝嗽跇?shù)林里發(fā)現(xiàn)了一具尸體阁将,經(jīng)...
    沈念sama閱讀 44,186評(píng)論 1 303
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡,尸身上長(zhǎng)有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 36,516評(píng)論 2 327
  • 正文 我和宋清朗相戀三年囤躁,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了冀痕。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片。...
    茶點(diǎn)故事閱讀 38,650評(píng)論 1 340
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡狸演,死狀恐怖言蛇,靈堂內(nèi)的尸體忽然破棺而出,到底是詐尸還是另有隱情宵距,我是刑警寧澤腊尚,帶...
    沈念sama閱讀 34,329評(píng)論 4 330
  • 正文 年R本政府宣布,位于F島的核電站满哪,受9級(jí)特大地震影響婿斥,放射性物質(zhì)發(fā)生泄漏。R本人自食惡果不足惜哨鸭,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 39,936評(píng)論 3 313
  • 文/蒙蒙 一民宿、第九天 我趴在偏房一處隱蔽的房頂上張望。 院中可真熱鬧像鸡,春花似錦活鹰、人聲如沸。這莊子的主人今日做“春日...
    開(kāi)封第一講書(shū)人閱讀 30,757評(píng)論 0 21
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽(yáng)。三九已至蛔钙,卻和暖如春锌云,著一層夾襖步出監(jiān)牢的瞬間,已是汗流浹背吁脱。 一陣腳步聲響...
    開(kāi)封第一講書(shū)人閱讀 31,991評(píng)論 1 266
  • 我被黑心中介騙來(lái)泰國(guó)打工桑涎, 沒(méi)想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留,地道東北人兼贡。 一個(gè)月前我還...
    沈念sama閱讀 46,370評(píng)論 2 360
  • 正文 我出身青樓石洗,卻偏偏與公主長(zhǎng)得像,于是被迫代替她去往敵國(guó)和親紧显。 傳聞我的和親對(duì)象是個(gè)殘疾皇子讲衫,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 43,527評(píng)論 2 349

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

  • 繪制像素到屏幕上 answer-huang22 Mar 2014 分享文章 一個(gè)像素是如何繪制到屏幕上去的?有很多...
    阿貍旅途T恤閱讀 1,626評(píng)論 0 7
  • 卷首語(yǔ) 歡迎來(lái)到 objc.io 的第三期孵班! 這一期都是關(guān)于視圖層的涉兽。當(dāng)然視圖層有很多方面,我們需要把它們縮小到幾...
    評(píng)評(píng)分分閱讀 1,757評(píng)論 0 18
  • 繪制像素到屏幕上 軟件組成 從簡(jiǎn)單的角度來(lái)看, 軟件堆椄莩蹋看起來(lái)有點(diǎn)像這樣: Display的上一層便是圖形處理單元...
    VanChan閱讀 832評(píng)論 0 1
  • 有很多種framework以及很多種方法的組合可以在屏幕上渲染UI元素枷畏,我們?cè)谶@里討論這個(gè)過(guò)程中發(fā)生的事情,希望這...
    縱橫而樂(lè)閱讀 4,482評(píng)論 4 25
  • 像素是如何顯示在屏幕上的呢虱饿? 當(dāng)然這里有很多種方式將某些東西顯示到顯示器上面拥诡,并且它們可能涉及到許多不同的fram...
    樗同學(xué)閱讀 1,767評(píng)論 1 3