OFD文檔解析流程

{"type":"doc","content":[{"type":"heading","attrs":{"align":null,"level":1},"content":[{"type":"text","text":"背景介紹"}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"之前的文章介紹了什麼是OFD,OFD中的各個元素的標識方法以及各個元素的定位方法。這次從顯示的流程上介紹一下如何把一個OFD文件顯示出來。"}]},{"type":"heading","attrs":{"align":null,"level":1},"content":[{"type":"text","text":"流程框架"}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"要把一個OFD文件顯示到屏幕上是有一定的流程的,首先要把這個文件讀入到內存中,然後按照OFD 的標準解析文件,最後在顯示設備上把解析是元素按照要求進行繪製。具體的流程可以用下圖進行表示:"}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"image","attrs":{"src":"https://static001.geekbang.org/infoq/ea/ea2c1cb96243242893f4ff247e0ba8ce.png","alt":null,"title":"","style":[{"key":"width","value":"100%"},{"key":"bordertype","value":"none"}],"href":"","fromPaste":false,"pastePass":false}},{"type":"heading","attrs":{"align":null,"level":1},"content":[{"type":"text","text":"框架解讀"}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"從圖中可以看出,首先是讀入OFD文件,然後按照標準解析文件,解析的內容大概有:"}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"bulletedlist","content":[{"type":"listitem","content":[{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"文檔的元數據信息"}]}]},{"type":"listitem","content":[{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"資源文件"}]}]},{"type":"listitem","content":[{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"大綱"}]}]},{"type":"listitem","content":[{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"電子簽章"}]}]},{"type":"listitem","content":[{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"註釋"}]}]},{"type":"listitem","content":[{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"頁面元素"}]}]}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":" "},{"type":"text","marks":[{"type":"strong"}],"text":"元數據信息"},{"type":"text","text":",我們可以比對一下PDF的文檔信息。一個pdf文件,可以獲取到他的作者信息,創建時間,修改時間等信息,同理,OFD也包含這些信息。"}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":" "},{"type":"text","marks":[{"type":"strong"}],"text":"資源文件"},{"type":"text","text":",對OFD的內嵌資源進行解析與提取,內嵌資源對比PDF的話最直接的就是查看文檔屬性,然後選擇字體,這樣就可以看到如下信息。"}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"image","attrs":{"src":"https://static001.geekbang.org/infoq/c7/c70a0b46211a5d5d4f4ad402f35af8b3.png","alt":null,"title":"","style":[{"key":"width","value":"100%"},{"key":"bordertype","value":"none"}],"href":"","fromPaste":false,"pastePass":false}},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":" 這些就是嵌入的資源。因爲一個文檔並不可能把所有的文字都顯示一次,所以就把該文檔所包含的字符組合成一個新的字體文件。所以,你會看到顯示的是嵌入子集。OFD解析的過程就是把這些字體,還有內嵌的圖片的路徑和這些元素的ID構建一張索引表,供後期顯示的時候查詢元素。"}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":" "},{"type":"text","marks":[{"type":"strong"}],"text":"大綱"},{"type":"text","text":"就是這個文檔的一個索引以及點擊這個大綱元素的動作信息,比如說點擊這個標題會跳轉到指定的頁碼。"}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":" "},{"type":"text","marks":[{"type":"strong"}],"text":" 簽章信息"},{"type":"text","text":",如何這個簽章信息包含印章圖片,那麼就需要按照上一篇文章所說的剝洋蔥的方法把圖片解析出來。然後顯示到指定的位置。"}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":" "},{"type":"text","marks":[{"type":"strong"}],"text":"註釋信息和元素信息"},{"type":"text","text":"都是由基本的元素構成的(圖片、圖形、文字)對於這三類元素,解析的元素信息就不太相同。"}]},{"type":"heading","attrs":{"align":null,"level":2},"content":[{"type":"text","text":"對於圖片資源:"}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"bulletedlist","content":[{"type":"listitem","content":[{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"圖片的編號,根據編號索引具體的圖片"}]}]},{"type":"listitem","content":[{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"圖片的外接邊框,圖片顯示的位置與大小"}]}]},{"type":"listitem","content":[{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"變換矩陣,對圖片進行旋轉或者變形"}]}]},{"type":"listitem","content":[{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"裁剪信息,限制圖片的顯示區域"}]}]}]},{"type":"heading","attrs":{"align":null,"level":2},"content":[{"type":"text","text":"對於文字"}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"可以分爲文件中有字體信息和沒有字體信息兩類:"}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"1)有字體信息"}]},{"type":"bulletedlist","content":[{"type":"listitem","content":[{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"字體的編號,根據編號索引具體的字體"}]}]},{"type":"listitem","content":[{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"字體的大小,獲取矢量圖的時候傳入的參數"}]}]},{"type":"listitem","content":[{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"外接邊框, 控制顯示的位置"}]}]},{"type":"listitem","content":[{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"填充顏色、勾邊顏色,控制顏色的顯示"}]}]},{"type":"listitem","content":[{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"裁剪信息,變換矩陣,控制字型的顯示區域以及顯示的形狀"}]}]},{"type":"listitem","content":[{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"文字的索引號,根據這個編號從字體中獲取到字型,可見字體解析這篇分享"}]}]}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"2)無字體信息"}]},{"type":"bulletedlist","content":[{"type":"listitem","content":[{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"字體的編號,根據編號索引具體的字體"}]}]},{"type":"listitem","content":[{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"字體的大小,獲取矢量圖的時候傳入的參數"}]}]},{"type":"listitem","content":[{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"外接邊框, 控制顯示的位置"}]}]},{"type":"listitem","content":[{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"填充顏色、勾邊顏色,控制顏色的顯示"}]}]},{"type":"listitem","content":[{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"裁剪信息,變換矩陣,控制字型的顯示區域以及顯示的形狀"}]}]},{"type":"listitem","content":[{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"文字內容,根據文字從系統字體中獲取字型"}]}]}]},{"type":"image","attrs":{"src":"https://static001.geekbang.org/infoq/c1/c17684fdb866cd7306ed2397d695961f.png","alt":null,"title":"","style":[{"key":"width","value":"50%"},{"key":"bordertype","value":"none"}],"href":"","fromPaste":false,"pastePass":false}},{"type":"heading","attrs":{"align":null,"level":2},"content":[{"type":"text","text":"對於圖形信息"}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"bulletedlist","content":[{"type":"listitem","content":[{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"圖形信息,可參考svg 的路徑表示方法"}]}]},{"type":"listitem","content":[{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"外接邊框,圖形的顯示位置"}]}]},{"type":"listitem","content":[{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"填充顏色和勾邊顏色,圖形的外觀"}]}]},{"type":"listitem","content":[{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"裁剪區域"}]}]}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"image","attrs":{"src":"https://static001.geekbang.org/infoq/cc/cc36c018838fc8df853e89ee0b7bdfea.png","alt":null,"title":"","style":[{"key":"width","value":"100%"},{"key":"bordertype","value":"none"}],"href":"","fromPaste":false,"pastePass":false}},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"heading","attrs":{"align":null,"level":2},"content":[{"type":"text","text":"元素繪製"}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":" 從圖中可以看出,繪製的過程只對OFD的資源信息(虛線)、簽章、註釋以及元素信息(實線)有關聯。因爲這些信息是需要顯示到設備上與用戶直接進行交互的元素。"}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"爲什麼要把資源信息用虛線表示?"}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":" 資源文件是繪製的基石,但繪製的時候並沒有直接體現出來,所以這裏用了虛線,而對於文字、圖片、圖形、印章圖片則是直接顯示到頁面上的。所以用了實線表示。"}]},{"type":"heading","attrs":{"align":null,"level":1},"content":[{"type":"text","text":"繪製方案"}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"對於如何把這些元素信息顯示到頁面上,可以有很多方案:"}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"1.利用OPENCV繪製一張圖片,顯示一張圖片"}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"2.把元素表示轉化成SVG的表示形式,嵌入頁面中顯示"}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"3.轉化成其他的格式,比如說PDF 用pdf.js 顯示"}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"4.利用其他的繪製工具進行繪製"}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"通過綜合考慮,選擇了第4種方案,這裏的其他工具我們選擇了java元素的AWT工具。原因如下:"}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"bulletedlist","content":[{"type":"listitem","content":[{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"操作簡單,學習成本低"}]}]},{"type":"listitem","content":[{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"功能強大,可以滿足顯示的所有的需求"}]}]},{"type":"listitem","content":[{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"座標系統和OFD的座標系統一致,都是以左上角爲原點"}]}]}]},{"type":"heading","attrs":{"align":null,"level":2},"content":[{"type":"text","text":"注意點"}]},{"type":"heading","attrs":{"align":null,"level":4},"content":[{"type":"text","text":"繪製單位"}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":" 在OFD種使用毫米(mm)來表示元素的大小,而AWT種則是使用像素(Px)。在繪製的時候需要把單位轉化一下。"}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":" 轉化過程種我們要使用一個參數(DPI),表示每英寸顯示幾個點。轉化的公式如下: "}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":" px / DPI = 英寸"}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":" 英寸 * 25.4 = mm"}]},{"type":"heading","attrs":{"align":null,"level":4},"content":[{"type":"text","text":"裁剪區"}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"裁剪區是用於限制元素的顯示範圍的,特別是在表格元素中,經常遇到文字長度超出了表格的長度,這時候就需要把文字的顯示範圍限制一下。具體效果如圖所示:"}]},{"type":"image","attrs":{"src":"https://static001.geekbang.org/infoq/2b/2bf72309df12776b191adfb962dd8a70.png","alt":null,"title":"","style":[{"key":"width","value":"75%"},{"key":"bordertype","value":"none"}],"href":"","fromPaste":false,"pastePass":false}},{"type":"heading","attrs":{"align":null,"level":4},"content":[{"type":"text","text":"顏色轉化"}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":" OFD的色彩空間比較簡單,僅僅支持RGB,CMYK,GRAY三種"}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":" 在繪製的時候,需要獲取他的色彩空間,一個簡單的辦法就是根據顏色的長度進行判斷"}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","marks":[{"type":"strong"}],"text":"色彩空間顏色長度示例(黑色)"},{"type":"text","text":"gray10rgb30 0 0cmyk40 0 0 100"}]},{"type":"heading","attrs":{"align":null,"level":4},"content":[{"type":"text","text":"繪製順序"}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":" 也許有人會問,這麼多元素是不是可以使用多線程進行繪製,答案呢是不可以。只能按照元素的順序進行繪製。因爲繪製過程就像是一個寫作業的過程,如果你手持幾根筆寫作業,可能會導致有些元素的覆蓋。"}]},{"type":"heading","attrs":{"align":null,"level":3},"content":[{"type":"text","text":"AWT避坑"}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":" JDK1.8的AWT在X86平臺的drawShape() 或者draw()函數是正常的,但是遷移到arm平臺下,會出現繪製問題,這裏可以使用OPENJDk解決。"}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"拓展閱讀:"}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"link","attrs":{"href":"https://xie.infoq.cn/article/14cc4c7acb5a6669c334a8a2b","title":null},"content":[{"type":"text","text":"OFD 版式技術解析系列(一):開篇"}]}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"link","attrs":{"href":"https://xie.infoq.cn/article/14cc4c7acb5a6669c334a8a2b","title":""},"content":[{"type":"text","text":"OFD 版式技術解析系列(二):OFD的顏色顯示 "}]}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"link","attrs":{"href":"https://xie.infoq.cn/article/bf0e4b6d48d319b100b46a633","title":""},"content":[{"type":"text","text":"OFD 版式技術解析系列(三):仿射變換在 OFD 中的應用"}]}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"image","attrs":{"src":"https://static001.geekbang.org/infoq/15/156168209e25b6853337c410c48f1696.png","alt":null,"title":"","style":[{"key":"width","value":"100%"},{"key":"bordertype","value":"none"}],"href":"","fromPaste":false,"pastePass":false}},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}}]}
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章