做個簡單的總結,最近缺少激情和動力。做事要順其自然,順勢而發,做必要的,幹這些也如此。先總結freetype的架構然後就是truetype的一些資料。========================================感覺這些東西都需要慢慢一步步的積累,一下子的話走不遠。
先總結freetype的架構吧。freetype用C實現物件導向,簡單的分析後,覺得整個庫做得簡單,實用,沒有太多累贅,順其自然,沒有太多刻意的封裝,累贅的介面調用,用起來方便,看起來舒心!
freetype設計得比較好的有幾個模組。stream,system, module,library, face
1,library管理著多個module,(sfnt,type1,src檔案夾下除了base之外的其他模組。)2,module管理著各個模組分析檔案的介面部分。例如 sfnt_interface;可以load_loca,load_cmap,lookup_table,goto_table;等。3,stream,system封裝一系列底層相關的api,而上層提供的stream給module的介面做分析用。4,FT_Face,TT_Face,TT_Face 是FT_Face的封裝,給內部用的,外部使用者只有FT_Face,而TT_Face則可以做分析資料用。在中間這層轉換做隔離封裝用。-----------------------------------------------------------------------
至於TrueType的檔案格式分析:1,注意truetype檔案是以大端序儲存的位元組序,讀取資料時要做轉換。2,最恍然大悟的是分析了cmap表,字元編碼本質就是給映射用的。最終還是流到圖元指令集。其實如果字型支援gbk編碼的話,可以不做unicode轉換也能夠顯示。不過貌似繪圖API只支援unicode的。format0儲存的是 ansii表的圖元索引映射,format4儲存的是unicode區段的圖元索引映射。format4 idRangeOffset不為0時,則根據*(idRangeOffset[i] / 2 + (c - startCount[i]) + &idRangeOffset[i])計算出,注意其中的位元組數位移,要換算為兩個位元組。3,另外一個有趣點的是glyf表,替換兩個字型檔的glyf表,或許可以做點偽造字型之類的事。4,分析檔案的一個頓悟,檔案格式儲存的是一個資料結構。-------------------------------------------------------------------------做檔案格式分析,常常感悟最多,畢竟檔案格式是儲存的單元,也是資料的彙總。附cmap表分析代碼一段:void ParserCmap(char* buff, char* buffend)<br />{<br /> char* buff_start = buff;<br /> USHORT version = readUnsignedShort(buff);<br /> buff += 2;<br /> USHORT tables = readUnsignedShort(buff);<br /> buff += 2;<br /> printf("version: %d, tables: %d/n", version, tables);<br /> int nTbIndex = 0;<br /> for (; nTbIndex < tables; ++nTbIndex)<br /> {<br /> USHORT flatformId = readUnsignedShort(buff);<br /> buff += 2;<br /> USHORT encodingId = readUnsignedShort(buff);<br /> buff += 2;<br /> ULONG offset = readUnsignedLong(buff);<br /> buff += 4;<br /> printf("flatformId: %d, encodingId: %d, offset: %d/n", flatformId,<br />encodingId, offset);<br /> char* table_start = buff_start + offset;<br /> USHORT formatId = readUnsignedShort(table_start);<br /> table_start += 2;<br /> if (formatId == 0)<br /> {<br /> printf("=====================format 0====================/n");<br /> USHORT length = readUnsignedShort(table_start);<br /> table_start += 2;<br /> USHORT version = readUnsignedShort(table_start);<br /> table_start += 2;<br /> printf("length: %d, version: %d/n", length, version);<br /> printf("byte: /n");<br /> int i = 0;<br /> for (; i < length; ++i)<br /> {<br /> printf("%c: 0x%x ", i, (*table_start & 0xFF));<br /> table_start++;<br /> }<br /> printf("/n");<br /> }<br /> else if (formatId == 4)<br /> {<br /> printf("====================format 4====================/n");<br /> USHORT length = readUnsignedShort(table_start);<br /> table_start += 2;<br /> USHORT version = readUnsignedShort(table_start);<br /> table_start += 2;<br /> USHORT segDblCounts = readUnsignedShort(table_start);<br /> table_start += 2;<br /> USHORT searchRange = readUnsignedShort(table_start);<br /> table_start += 2;<br /> USHORT entrySelector = readUnsignedShort(table_start);<br /> table_start += 2;<br /> USHORT rangeShift = readUnsignedShort(table_start);<br /> table_start += 2;<br /> printf("length: %d, version: %d, segDblCounts: %d, searchRange: %d,<br />entrySelector: %d, rangeShift: %d/n",<br /> length, version, segDblCounts, searchRange, entrySelector, rangeShift);<br /> char* endCounts = table_start;<br /> char* startCounts = table_start + segDblCounts + 2;<br /> char* delta = startCounts + segDblCounts;<br /> char* rangeOffset = delta + segDblCounts;<br /> char* glyfId = rangeOffset + segDblCounts;<br /> USHORT segCounts = segDblCounts >> 1;<br /> USHORT segIndex = 0;<br /> printf("endCounts startCounts delta rangeOffset/n");<br /> for (; segIndex < segCounts; ++segIndex)<br /> {<br /> USHORT endCode = readUnsignedShort(endCounts);<br /> endCounts += 2;<br /> USHORT startCode = readUnsignedShort(startCounts);<br /> startCounts += 2;<br /> USHORT del = readUnsignedShort(delta);<br /> delta += 2;<br /> USHORT offset = readUnsignedShort(rangeOffset);<br /> rangeOffset += 2;</p><p>//for wingdings find 0xf031 match 49:'1'<br />/* if (segIndex == 0)<br /> {<br /> USHORT dis = offset / 2 + 0xf031 - 0xf020;<br /> rangeOffset += dis * 2 - 2;<br /> USHORT id = readUnsignedShort(rangeOffset);<br /> printf("0xf031: 0x%x/n", id);<br /> }<br />*/<br /> printf("0x%x 0x%x %d %d/n", endCode, startCode, del, offset);<br /> }<br /> int glyfIndex = 0;<br /> while (glyfId < buffend)<br /> {<br /> USHORT glyf = readUnsignedShort(glyfId);<br /> glyfId += 2;<br /> printf("%d: 0x%x ", glyfIndex, (glyf & 0xFFFF));<br /> glyfIndex++;<br /> }<br /> printf("/n");<br /> }<br /> }<br />}