最美情侣中文字幕电影,在线麻豆精品传媒,在线网站高清黄,久久黄色视频

歡迎光臨散文網(wǎng) 會員登陸 & 注冊

文本布局性能提升 60%,Inline Text 技術(shù)原理與實(shí)現(xiàn) | Cube 技術(shù)解讀

2022-09-14 15:46 作者:支付寶體驗(yàn)科技  | 我要投稿

?????♀? 編者按:本文為《Cube 技術(shù)解讀》系列第五篇文章,作者是作者是螞蟻集團(tuán)客戶端工程師弘祖,重點(diǎn)闡述 Inline Text 技術(shù)原理與實(shí)現(xiàn),歡迎查閱~

第一篇:支付寶新一代動態(tài)化技術(shù)架構(gòu)與選型綜述 | Cube 技術(shù)解讀

第二篇:Cube 卡片技術(shù)棧詳解 | Cube 技術(shù)解讀

第三篇:Cube 小程序技術(shù)詳解 | Cube 技術(shù)解讀

第四篇:Cube 渲染設(shè)計(jì)的前世今生 | Cube 技術(shù)解讀

第五篇:本篇

第六篇:大屏小程序探索實(shí)踐 | Cube 技術(shù)解讀

支付寶客戶端有極強(qiáng)的動態(tài)化訴求,不論 iOS 還是 Android 平臺,重新分發(fā)軟件包在時間上、效率上都難以滿足產(chǎn)品運(yùn)營的要求,所以客戶端動態(tài)化技術(shù)應(yīng)運(yùn)而生。

Cube 起源于 Native 頁面的動態(tài)化訴求,產(chǎn)品形態(tài)表現(xiàn)于 Cube 卡片。隨著小程序的出現(xiàn),Cube 融入了支付寶小程序技術(shù)棧,產(chǎn)品形態(tài)為輕量級的支付寶小程序解決方案(相對于使用瀏覽作為核心的 Web 小程序)。作為一個輕量級引擎,Cube 小程序具有體積小、啟動快、內(nèi)存占用低的特點(diǎn),我們使用自研渲染技術(shù),支持 CSS 子集來實(shí)現(xiàn)這些特點(diǎn)。

與瀏覽器不同,Cube 小程序引擎的輸入是一個小程序 DSL(可以理解為小程序規(guī)范的語言) 構(gòu)建后的產(chǎn)物(產(chǎn)物主要由一個 JS 文件以及相關(guān)資源組成)輸出為用戶界面以及后續(xù)的交互(不斷的用戶輸入和 UI 輸出)。Cube 小程序不斷迭代支持樣式表,Inline Text 能夠做到在較小的包體積(主 so 只有 2.8 MB)的情況下,支持非常多的 CSS ?樣式,并且布局繪制與 Web 瀏覽器幾乎完全一致。

Inline Text

什么是?Inline Text?呢?這要從布局引擎開始介紹,布局引擎又稱排版引擎,是一個軟件組件,負(fù)責(zé)獲取標(biāo)記或者元素結(jié)合樣式產(chǎn)生相應(yīng)的位置、大小以及層級等排版結(jié)果。這個排版結(jié)果可以被用于輸出到顯示器也可以被輸出到打印機(jī)。Cube 引擎使用了 2 個布局引擎,卡片使用了?Yoga,用于高性能布局場景,小程序使用了?Flow Layout。其中 Flow Layout 支持 Flow 布局(流式布局),具有代表性的樣式為 display:block ,也就是 Web 中 div 等元素的默認(rèn)布局行為。

布局引擎的一個重要工作就是文字的排版工作,而大多數(shù)非 Web 渲染的技術(shù)棧(包括老版本 Cube )使用的是平臺層的文本布局對象,在布局階段根據(jù)計(jì)算好的樣式構(gòu)造平臺層文本對象,計(jì)算好寬高位置后再傳遞回布局引擎,完成布局;后續(xù)繪制時使用創(chuàng)建好的平臺層對象進(jìn)行繪制。

使用平臺層對象在布局階段會產(chǎn)生一定程度的性能損耗,這種損耗主要包括兩部分:一是消耗在操作系統(tǒng) API 對文字的布局計(jì)算消耗;另外一種是布局引擎與平臺層交互時產(chǎn)生的性能損耗。這種實(shí)現(xiàn)導(dǎo)致文本只能夠以一個一個矩形存在,難以靈活地圖文混排,也難以將一段文字中的部分文字加顏色和樣式,這也是與 Inline 相關(guān)的樣式的含義,典型與?Inline?相關(guān)的樣式有:display:inline 、 display:inline-block 、display:inline-flex 、float:left。以下2個圖片就是這種能力的典型代表。

圖片
圖片

除卻非常明顯的能力以外,符合相關(guān) Web 標(biāo)準(zhǔn)一直是 Cube 小程序的技術(shù)目標(biāo)之一,下面舉一個例子來說明。請看如下代碼( HTML 代碼 小程序可以換為 view 和 image標(biāo)簽)

是一個可替換元素。它的 display 屬性的默認(rèn)值是 inline,但是它的默認(rèn)分辨率是由被嵌入的圖片的原始寬高來確定的,使得它就像 inline-block 一樣,它放置的位置是由文本的基線決定的,這個例子中雖然沒有任何文字,但是 img 在排版布局的時候是依賴文字的基線,所以 font-size 會影響 img 的位置,又由于 font-size 是繼承的,如果是動態(tài)下發(fā)的元素,不小心在祖先設(shè)置了大小不符合預(yù)期的字體就會影響布局和繪制的結(jié)果。這個小例子說明了文字對于一個引擎在布局時的影響,可見文字對于頁面排版布局的影響是多方面的。作為一個布局引擎,Flow Layout?需要完美的復(fù)刻這些行為,Cube 面向標(biāo)準(zhǔn)又邁出了一步。

總結(jié)以上幾點(diǎn),Cube 團(tuán)隊(duì)決定在 Cube 引擎上將文本相關(guān)能力增強(qiáng),其中包括了對文字的寬高的測量與計(jì)算,排版和布局,在增強(qiáng) CSS 能力的同時又可以提升布局性能,這些文字相關(guān)的能力(或者叫 Feature )統(tǒng)一被稱為?Inline Text?,還原前端開發(fā)者在使用 Cube 引擎時對文字等樣式的舊有使用習(xí)慣,大幅提升開發(fā)體驗(yàn)。進(jìn)而 Cube 小程序能夠承載更多的小程序,進(jìn)而實(shí)現(xiàn)更大的業(yè)務(wù)價(jià)值。

實(shí)現(xiàn)細(xì)節(jié)

對于?Inline Text?在 Cube 引擎中的實(shí)現(xiàn)分為兩部分:一部分是在?Flow Layout?去掉對接文本平臺層部分,增強(qiáng)為直接對文字的寬高進(jìn)行排版測量,我們稱為?文本布局?。另外一部分是繪制,本次實(shí)現(xiàn)依然使用平臺層繪制,只不過使用了更低一級別的 API,減少操作系統(tǒng)的計(jì)算,盡可能直接調(diào)用繪制 API,我們稱為?文本繪制。為了更好的理解這兩部分的關(guān)系,以及實(shí)現(xiàn)細(xì)節(jié),我們先了解一下?光柵化和?文本自繪制?。

光柵化

我們都知道像素的概念,計(jì)算機(jī)世界是離散的,每一條線,每個字繪制出來都需要到一個一個像素點(diǎn)上,這個從矢量圖形到像素的過程叫做光柵化,就像柵格一樣??梢詤⒖家韵聢D片:

圖片

文本自繪制

與文本自繪制相對應(yīng)的是現(xiàn)有的渲染流程中對于文字的布局以及渲染都使用了平臺層(OS)的 API,也就是 Cube 引擎下 platform 模塊中的邏輯。布局時創(chuàng)建對應(yīng)的平臺層對象,通過平臺層計(jì)算出文本矩形的區(qū)域然后把結(jié)果傳遞回布局引擎,拿到結(jié)果完成布局。后續(xù)繪制時,使用創(chuàng)建好的平臺層對象進(jìn)行繪制。

文本自繪制是指通過布局引擎直接測量文本的寬高,在合適的區(qū)域進(jìn)行擺放,從而完成布局;后續(xù)的繪制也直接通過字體的信息(一些描述字形的信息)直接進(jìn)行光柵化。

Cube 在技術(shù)迭代的過程中先進(jìn)行前半部分布局部分,后半部分隨著整個引擎的自繪制一起完成。所以現(xiàn)階段的方式是布局引擎布局完成后,使用平臺層 API 進(jìn)行繪制,過程可以參考以下圖片:

圖片

文本布局

為了將文字正確的放置到屏幕或者說一個矩形的正確位置上,我們分為兩步,第一步先把每一個字符的寬高計(jì)算出來,第二步進(jìn)行布局計(jì)算(擺放文字和其他東西例如圖片等)。需要注意的是真正的程序在運(yùn)行的時候有時候會采用更高效的計(jì)算方式,未必需要完全測量每一個字符的寬高,例如等寬字體。

?1??單個字符寬高計(jì)算

常見的?sans-serif,serif,monospace?被稱為通用字體族,他們叫通用字體族也就說他們代表了一系列字體族(FontFamily),交由布局引擎去操作系統(tǒng)中尋找合適的字體。字體族被稱為字體族說明一個字體有時候會提供多個版本,這是為了滿足不同的樣式需要,那么選定了一個字體的其中一個版本后我們稱之為?Typeface,Typeface 包含了很多文字,其中每一個單個文字(針對同一個Unicode字符)我們稱為?Glyph?,每一個 ?Glyph 中都包含了一個單個文字信息,對于當(dāng)代?TrueType?矢量字體,單個文字信息又由多條?貝塞爾曲線 組成,我們稱之為矢量圖形,根據(jù)字體的大小可以得到一個明確的大小的文字,再應(yīng)用上一些樣式以后經(jīng)過光柵化就可以得到單個字符的寬高。

下面是一個對比的小例子,對于同一個字體,字體的作者會一般來講會提供兩種一種是正常寬度的字體,另外一種是加粗的字體,這個加粗被稱為?font-weight?,那一個加粗一個不加粗就代表了兩種?Typeface?,根據(jù)之前的介紹那么就會有兩套?貝塞爾曲線?來描述同一個 Unicode 字符,以下是不加粗和加粗字符Y的曲線??梢韵胂癯鰜砣绻煮w的作者針對傾斜(italic)單獨(dú)提供了一個?Typeface?也會像加粗一樣擁有單獨(dú)的曲線描述。


圖片


下面介紹一下 TextStyle 。根據(jù)上文描述,一個字符最后確定大小除了 ?Typeface 以外還需要加上一些文本的樣式最后才能確定字符寬高,這些樣式我們統(tǒng)稱為 TextStyle 。了解了 Typeface 等概念以后,我們就會發(fā)現(xiàn)繪制一個字體除了 Typeface、文字大小還需要其他參數(shù),比如:color,font-size,是否需要應(yīng)用 FakeItalic,是否需要 FakeBold(稍后解釋),等很多參數(shù)。這些除去了 Typeface 以外的信息被抽象為 TextStyle。在確定了 Typeface 以后還需要 TextStyle 信息再經(jīng)過光柵化后才能夠知道一個字形最終渲染的寬高(由于矢量 Typeface 的特點(diǎn),取寬高未必一定需要光柵化,經(jīng)過特定的比例計(jì)算亦可)。

根據(jù)之前的描述,假如字體的作者沒有為字體設(shè)計(jì) font-weight 對應(yīng)的 Typeface,也沒有為 italic 設(shè)計(jì)Typeface,那么在用戶指定相關(guān)樣式的時候應(yīng)該怎么辦,這時候 Fake 相關(guān)變換就上場了,他可以直接變換原有的字體的曲線來達(dá)到看起來變粗和變傾斜的了效果,這時候 FakeItalic 以及 FakeBold 就會應(yīng)用到字體上,通過提前預(yù)制的變換函數(shù),此時 TextStyle 就包含了 FakeItalic 和 FakeBold,反之則不包含。有時候是否應(yīng)用 Fake 相關(guān)變換由布局引擎自行決定。

為了計(jì)算文字相關(guān)能力我們引入了一些 Library,主要為 Skia 和 Harfbuzz,其中 Skia 裁剪掉了所有繪制部分只保留針對文本的相關(guān)抽象,而 Harfbuzz 用于最終測量文本的寬高的庫,Harfbuzz 使用 Skia 提供的關(guān)于 Typeface 以及 Glyph 的接口。以下簡單介紹以下 SkTypeface 對于 Typeface 的抽象,以及字體在各個平臺初始化的細(xì)節(jié)。

在 Skia 庫中,SkTypeface 抽象了 Typeface 下面的細(xì)節(jié)實(shí)現(xiàn)庫 FreeType (Android), CoreText (iOS),提供了最基礎(chǔ)的功能,比如把 Unicode 轉(zhuǎn)換為字體中具體字形的 index(針對 Glyph 的抽象),比如:直接通過 index 取或者計(jì)算單個文字輪廓的抽象,在 Android 通過 FreeType 庫讀取系統(tǒng)的字體文件,在 IOS 上通過 CoreTextAPI 讀取相關(guān) table 數(shù)據(jù)(Typeface 元數(shù)據(jù))直接構(gòu)造。

字體初始化細(xì)節(jié)同瀏覽器實(shí)現(xiàn)邏輯一致,在 Android 上使用/etc/fonts.xml中的字體信息,老版本的Android 系統(tǒng)使用/system/etc/fonts.xml等類似的4個位置。其中定義了操作系統(tǒng)提供的字體,以及對應(yīng)的 font-family、font-weight、font-style, ?language 初始化后準(zhǔn)備好后續(xù)布局時候找到合適的 Typeface。IOS 上直接使用 CoreText API 獲取相關(guān)字體列表以及信息。

至此我們就擁有了測量單個文字的能力,通過系統(tǒng)以及用戶輸入找到對應(yīng)的 Typeface 配合 TextStyle ,最后使用 Harfbuzz 將文字寬高計(jì)算出來。(這里是為了方便理解,實(shí)際上可以一次測量多個文字的寬高)

?2???布局計(jì)算

首先是布局樹和樣式表,這里不過多介紹,通過 CSS 樣式加上相關(guān) Element,構(gòu)建出布局樹,在進(jìn)行布局之前每一個元素都通過樣式表計(jì)算有了自己的 ComputedStyle,block 元素,flex 元素按照其默認(rèn)行為開始布局。inline 元素在自己的 LayoutBlockFlow 中開始布局,根據(jù) ComputedStyle 中的 font-family 確定一個 FallbackList,然后根據(jù)字體以及文本以及 white-space 等相關(guān)信息邊測量文本的寬度,此處引入了 ICU ,這個庫用于分割不同的語言,以及確定是否需要斷句,標(biāo)點(diǎn)符號是否放到下一行或者留在上一行,然后根據(jù) Unicode 字符所在的區(qū)間,最后確定出 TextRun,最后組成一個一個 LineBox,用于后續(xù)繪制使用。此處描述較為精簡,后續(xù)會有單獨(dú)一篇文章展開講布局過程。

文本繪制

?1???對接平臺層繪制

由于 Inline Text 的特性,必須進(jìn)行繪制鏈路的改造。整個渲染鏈路不過多介紹(請參考其他相關(guān)文章),Cube 繪制流程主要的結(jié)構(gòu)是渲染樹(內(nèi)部稱為 RenderTree ),這棵樹有很多節(jié)點(diǎn),用于描述父子關(guān)系,其中文本節(jié)點(diǎn)在現(xiàn)階段屬于葉子節(jié)點(diǎn), 在遞歸進(jìn)行繪制的時候,原有由于文字是一個一個矩形,所以整個 Text 是使用同一個 border 繪制流程以及背景繪制流程,由于 inline 特點(diǎn),繪制到文本節(jié)點(diǎn)時,對于背景以及 border 的繪制流程需要根據(jù)每行來進(jìn)行繪制,增加了一層循環(huán),對于背景以及 border 折行等有諸多細(xì)節(jié)要處理,此處要對齊 Web 的繪制效果。后續(xù)如果要支持更復(fù)雜的文字特性,讓文本節(jié)點(diǎn)變?yōu)榉侨~子節(jié)點(diǎn),還需要進(jìn)一步增強(qiáng)繪制流程。

文本經(jīng)過上一階段布局計(jì)算以后,通過 LineBox 上的信息針對每一個 Text 節(jié)點(diǎn)(span)產(chǎn)生了三個數(shù)據(jù)結(jié)構(gòu)用于繪制:

展示以上偽代碼是為了更好的理解對接平臺層繪制的細(xì)節(jié),TextStyle 就是之前介紹過的除 Typeface 以外繪制需要用的其他信息,由于 Element 的特點(diǎn),同一個 Element 下的樣式是一致的,所以一個 Text 節(jié)點(diǎn)一份 TextStyle,然后是一堆 TextLineInfo,每一個代表一行的數(shù)據(jù),每一行里面有好多個 TextRun,代表著每段對應(yīng)的 Typeface 以及子串的始末,在布局的時候已經(jīng)提前進(jìn)行平臺側(cè) Typeface 的創(chuàng)建,等到繪制階段直接通過 typefaceId 拿到對應(yīng)的對象繪制即可。其中 Android 平臺在布局的時候直接使用 Android 的 API android.graphics.Typeface 創(chuàng)建,iOS 平臺由于 SkTypeface 是直接針對 CoreText 對象進(jìn)行抽象,所以繪制的時候直接使用包裹的 CoreText 相關(guān)字體對象進(jìn)行繪制即可。

包體積

根據(jù) Cube 引擎自身的定位以及小程序的對于文本渲染能力的訴求,Inline Text 對 Skia、Harfbuzz、ICU、Freetype 等進(jìn)行了深度優(yōu)化和定制。Cube 在包體積上面做了大量的工作,針對引入的庫均做了大量的裁剪,例如 Skia 的繪制部分,去掉一些 Harfbuzz 中不必要的邏輯,針對 ICU 還定制實(shí)現(xiàn)了自己的部分,Inline Text 的實(shí)現(xiàn)(包含所有依賴庫)最終將 Cube 包體積的增加控制在 170kb 左右。

體驗(yàn)與應(yīng)用

豐富的 CSS 樣式與能力

在 Cube 引擎支持 Inline Text 以后,樣式 float、display:inline-block 以及 flex 布局中多個元素的基線對齊等細(xì)節(jié)都得到了完善,做到幾乎和瀏覽器引擎布局結(jié)果完全一致。

以下是一些 Inline Text 能力表現(xiàn),布局引擎具有遞歸以及套娃特點(diǎn),例子中也有體現(xiàn):

  • 大段文本中的部分文本使用不一樣的樣式:

圖片
  • float:left

圖片
  • float:left “套娃”

圖片
  • CJK 文本 配合 word-break:keep-all, 無數(shù)個風(fēng)暴折行不會斷開:

圖片


  • font-family Fallback 機(jī)制

當(dāng)我們在 CSS 中寫如下代碼的時候意味著:

其中123,456使用 alipay-number, 但是中國使用系統(tǒng)的 serif 字體。原因是 alipay-number 字體沒有提供中國這兩個 Unicode 的 Glyph。

這個特性好多非 Web 的渲染引擎支持得都不完善,它涉及到 Typeface 的選擇規(guī)則以及繪制,Inline Text 完美復(fù)刻了 Web 渲染引擎的 Fallback 機(jī)制。

  • font-face 的支持

第三方字體是常見需求,很多業(yè)務(wù)都無法滿足于系統(tǒng)字體,一般來講可以內(nèi)置在包里,或者是通過 URL 獲取。瀏覽器的 CSS 在第三方字體準(zhǔn)備好以后,通過 CSS 選擇器重新觸發(fā)匹配規(guī)則通過 FontSelector 重新選擇對應(yīng)的 Typeface,完成重繪。

與瀏覽器不同,Cube 引擎的樣式匹配非常精簡,在第三方字體下載以后,清理掉之前的對應(yīng)的 font-face的文本緩存,重新觸發(fā)布局繪制達(dá)到同樣的效果。又由于樣式表的加持,以及 Inline Text 對于 ICU 的接入,font-icon 可以使用偽元素(content)加上私有 Unicode 的方式直接使用,和 Web 體驗(yàn)完全一致。

圖片

性能提升

文本布局的性能提升是由于使用了文本測量由布局引擎進(jìn)行排版以后,以前的與平臺層的 JNI 交互沒有了,平臺層對象的創(chuàng)建與布局邏輯也沒有了,文本布局的性能有了大幅提升:

圖片

應(yīng)用場景

目前在優(yōu)酷 OTT 上 90% 由搭建平臺產(chǎn)生的產(chǎn)物都默認(rèn)開啟了 Inline Text,使用了相關(guān)能力,提升布局的性能,由于協(xié)議頁面的需求,開發(fā)者無需再使用 Javascript 進(jìn)行分詞更換顏色,直接使用引擎能力,可以參考以下頁面,此頁面應(yīng)用 Inline Text 后頁面加載時間僅為原來的 1/3:

圖片

未來與展望

當(dāng)前 Inline Text 是 1.0 版本實(shí)現(xiàn),2.0 版本的規(guī)劃如下:

  • 根據(jù)目前 Cube 繪制模型,增強(qiáng)支持 textNest(可以理解為 span 標(biāo)簽的嵌套);

  • 采用自繪制后端(比如:Skia),直接通過字體信息光柵化達(dá)到全平臺一致性;

  • 支持豎向文本布局;

  • 支持阿拉伯等雙向文本;

  • 支持更多的富文本特性;

  • 進(jìn)一步優(yōu)化超長文本布局計(jì)算耗時。

附錄:Inline Text 支持的樣式

圖片
圖片
圖片
圖片


文本布局性能提升 60%,Inline Text 技術(shù)原理與實(shí)現(xiàn) | Cube 技術(shù)解讀的評論 (共 條)

分享到微博請遵守國家法律
古丈县| 蒙城县| 二连浩特市| 佛坪县| 彭泽县| 泰和县| 武汉市| 诏安县| 宝应县| 苏尼特左旗| 英吉沙县| 河西区| 宁陵县| 福建省| 玉溪市| 罗源县| 大石桥市| 巴东县| 安达市| 佛坪县| 华宁县| 温泉县| 当涂县| 桃园县| 弥勒县| 雅江县| 延安市| 呼图壁县| 财经| 襄樊市| 辽宁省| 阿瓦提县| 金湖县| 宜宾县| 池州市| 马鞍山市| 阳高县| 平顺县| 无棣县| 湖州市| 南皮县|