轉自IMWeb社群,作者:黎騰,原文連結
前言
編碼,是每個程式設計師繞不開的話題。對於前端工程師而言,字元更是會直觀地展示在介面上。
提起文字,大部分人的腦中,都會定式為規整排列的字元。但是林子大了什麼鳥都有,世界上可是存在著6800+種文字,難免會飛出來一些詭異的鳥…
而號稱“萬國碼”的Unicode,在實現編碼與展示的時候,也會不會遇到一些奇葩的事情呢?
事實上,可能你早已見識過了:
x̙͈̝͍͕̙̄͛̽̆͌́̕͟g̘̣̠̝̟̤̥̼̼̽͑͋̈̑̒͟͞q̛̤̦̝̘͎͋̔̋͌͒̆̋̚͡f̵̢̙͇̮̠̋̀͌̅̉̃̔͜͜͠͡r̢̜̩͙̭̲͓͈̈̀͑̆͋̚͢͜m̷̛͙̝̣̲̭͍͉̊̓̾̈̋̿̚͢͟͠s̷̡̩͔̮͈̜̊̽͂̆̈́̃̓͋̏
熱҈的҈字҈都҈出҈汗҈了҈
你的螢幕被藍翔挖掘機給挖壞了不信你看;̷̸̨̀͒̏̃ͦ̈́̾̀́̎͢҉̵̶͚̼͉͖̺̥͔͇̰̹̮͙͉̻̼̭̻͕̮͇ͨͬͪ͗̇̑̽͋̀̋̊͌ͧͨͭ̓̅͐ͥ̂̔̊ͧ͊҉̶̵̷̞̩̦̳̺̳̬̬̩̣̫͇̯̥͖͍͕̠̦̼̗ͯ̽͌̔ͪͯ́́͋̍ͨ̿̿̎͒ͤ̓̅̀͂ͧ͋̏ͫͣ̔͘͜͠͏̶̵̸̧̧̥̺͓̘̺͎̜̥͕͈̝̫͎̺̮̱̤̠̠͖̳̻̥̣̪͍͕͇̮͙̹̪ͮͧͫ͂͒ͤͣ̌̽ͨͪ͒̄̄̉̒̊ͩ̅͆͘̚͘͘̚͟͟͝ͅ
今天我們就來探討一下這些奇怪的字元。
一、文字可以戴帽子和穿鞋子
提起泰文,很多朋友都會立即想到:薩瓦迪卡(你好)。
但這句話是怎麼寫的呢?
其實這句你好,男生和女生之間還有差異,男生寫法是:สวัสดีครับ
,女生則是:สวัสดีค่ะ
。
不過這並不重要,重要的是,我們發現某些字的上面,還帶了特殊的符號。就好像是戴上了帽子。
事實上,泰文字元不僅會“戴帽子”,偶爾還會“穿鞋子”。
比如下面三個字元:ผ ผู ผู้
如果腦洞再大一點,有人就會想,那是不是還可以戴多頂帽子呢?
的確如此…泰文允許你穿一雙鞋子,並且戴兩頂帽子。完整的形式是這樣的:
所以,平時看慣了中英文的我們,需要改變一下思路了。
世界上的文字,並不全是規規整整橫向排列的格子,也存在像泰文這種變形金剛組合式的文字。
雖然標準的泰文裡,“帽子”和“鞋子”的數量是有限制的,但由於國際碼的迷之設計(先賣個關子),在計算機裡顯示的泰文字元,卻可以擁有無數的帽子和鞋子。也就是說,它變成了一款可以在Y軸無限擴充的文字!
並且,我們不光可以往上噴,還可以有一定角度…
還可以
,簡直是不講道理。(由於一些系統會崩潰,這裡使用截圖)
二、人與機器的矛盾
然後我們會質問Unicode,你為何不講道理?
如此的設計,近乎是一個bug;但即使是bug,也應該早就修復了呀。
事實上,這樣的設計,是為了解決一個問題:人與機器的矛盾。
首先是儲存的矛盾。
如果把每個組合好的泰文用一個編碼來表示,那麼至少需要44×21×4=3696個編碼(實際上可能要比這還多)。用如此多的編碼來處理基本元素只有69個的文字是非常浪費的,因此電腦採用一套稱為複雜文字編排(CTL)的設計來解決矛盾。
簡單的說,泰文的每個基本字元對應一個編碼,使用者在輸入法裡依次輸入多個基本字元進行拼合,最後敲一個特殊的“結束字元”;這時前面輸入的基本字元,就拼合成了一個單獨的泰文字元,在螢幕中顯示。
這樣就解決了儲存的空間浪費問題。
但這樣就帶來了第二個矛盾,識別的問題。
人可以輕鬆地識別一個泰文合字是否拼寫正確、有意義;但機器在顯示時卻很難進行判斷,即使可以也會帶來相應的效能問題。
如何解決呢?如今會在輸入法上做一些文章,比如打一個聲調符號後就不能再輸入了。不過,由於泰文這種基於結束標誌合成字元的本質,你還是沒法避免“藝術家”們使用複製貼上、手工撰改字元位置等方式去進行創造,只能起到一些限制作用。
其次,在比較新版本的Webkit裡,在顯示上會阻止這種往上下冒的字元,這樣至少不影響排版。所以有部分字元已經不會出現上下疊加的情形了,你可以在不同瀏覽器,觀察一下這個字元的顯示:ส็็็็็็็็็็็็็็็็็็็็็็็็็็็็็็็็็็็็็็็็็็็็็็็็็็็็็็็็็
三、萌即正義的顏文字 (ง •̀_•́)ง
也許你覺得泰文奇葩,但它的聲調就在文字裡,看到就能準確地讀出來。這樣更容易傳播,是不是也沒了你讀文言文要查字典的煩惱呢?所以文字的設計各有優劣。
這樣的設計不止泰文,它只是一個典型的例子。除此之外常見的還有寮國文、藏文。
腦洞大開的藝術家們,又會想到另外一個好玩的事情:我能不能拿寮國文的“帽子”,組合“藏文”的鞋子,合成一個獨立的字元呢?
他們贏了。不久,顏文字開始流行。
比如,這個表情:(;´༎ຶД༎ຶ`)
裡面有眼睛流淚的一個字元:༎ຶ
它是什麼語言呢?
事實上,它並不屬於世界上任何一種語言!眼睛部分是寮國文,淚水部分屬於藏文。
但是,你在複製它的時候,可以發現它卻是一個單獨的字元,這就非常的神奇。原因我們在第二部分已經講過了。
我是如何知道的呢?當然我並不是個語言學家,我們可以轉碼一下,發現༎ຶ
對應的編碼是\u0f0e\u0eb6
,再到 unicode-table 裡去檢視就清楚了。
除此之外——
- ▷ˋε´◁ 中 ε 是希臘字母
- ʕ-'ᴥ’-ʔ 中 ʕᴥʔ 是國際音標
- (·ཀ·」∠) 中 ཀ 是藏文
- (ง •̀_•́ )ง 中 ง 是泰文
- 罒 д 罒 中 罒 是中文(同網),д 是俄語西裡爾字母
看來如果你會發顏文字,就是名副其實的會“十八國語言”了呢 (๑✦ˑ̫✦)✧
四、字型的錯位
前面我們一直在談字元的本質,但字元在螢幕中的展示,還有一個關鍵的因素:字型。
相同的字元,使用了不同的字型,它們的顯示也會有差別。
一行中文,你設定“黑體”或“草書”,它大體來看還是規整的;
但如果你設定一行英文為“草書”,可能就會有問題。
在瀏覽器裡,如果對應編碼在字型檔案裡為空,一般會展示成一個方格,起碼不會影響其他正常字元的排版。但我們知道,Unicode的林子實在太大了…
在某些字型裡,就會對一些特殊的字元產生錯誤的排版。
比如:熱҈的҈字҈都҈出҈汗҈了҈
把它轉義一下,就得到編碼是: \u70ed\u0488\u7684\u0488\u5b57\u0488\u90fd\u0488\u51fa\u0488\u6c57\u0488\u4e86\u0488
其中0488
就是҈
這個字元的編碼,它是一個組合用的西里爾文百千符號。
它在大部分常用字型裡,都有錯位問題;而其他一些字型,比如 Courier New 字型,則是分開的展示:
那麼,這兩種展示哪種才是正常的呢?其實都不正常。
我們檢視西里爾文計數法的wiki,可以看到它只有配合西里爾數字時,才能展示正常:
至於你把它跟其他語言組合在一起時,我們要麼看到錯位,要麼看到分離的展示。而且國際上並沒有一個組織,去規定要怎麼展示。事實上文字這麼多,根本也管不過來,所以這也是混亂的原因。
最後補充一點,另外一小撮別有心裁的藝術家,還習慣使用這個字元去突破敏感詞過濾…
五、混亂與創新?
值得一提的是,Unicode是不可阻擋的潮流,它也一直在更新。比如我們常用的Emoji表情,就已經是Unicode的標準字符集。
而前面我們說到,大家在玩這些奇奇怪怪的字元時,都是基於“類似bug”的設定在搞事情。這就有很大的侷限性。
那“藝術家”們又會有些大膽的想法:我能不能主動創造一些新字元,就是為了錯位和組合呢?
我也不清楚這是創新,還是會帶來更多的混亂。但事實是,iOS系統自帶的字元,已經有這樣的嘗試了。並且搜狗輸入法在iOS系統提供的諸多符號裡,挑選了一些,可供使用者去使用。這個功能的名字,叫做花漾字。
還是得感慨藝術家們的視角是多麼獨特。
既然都這樣了…最後,希望我們的國產表情包能有朝一日打入Unicode吧。
(未完待續)