2013年12月24日 星期二

利用Pango來區分不同書寫系統的文字

各位超級久不見。忙著學語言...(鞠躬)。不過也正是因為忙著學語言,才有今天這個主題。

基本上來說,我的語言筆記會呈現一定的樣式。例如說單字筆記就一定會是單字、翻譯、解釋以及例句。課文筆記一定有課文,還有(可能)每個字的解釋,相關文法等。如果說可以用一個統一的格式來表示,然後利用文件產生器來生產pdf檔的話應該很棒對吧~就說我超懶的!

要產生這樣的pdf文件,就必須要進行排版;要排版則需要有文字的語言資訊,才可以恰當的做斷行。同時,也必須確保繪製系統可以選擇系統內相對應的字型,也要有恰當的文字排列引擎等等。要收集這些資訊很曠日費時,很麻煩,要懂unicode,要懂fontconfig...所幸我們現在有pango來替我們把這些資訊整理好列出以供我們使用。

程式碼請見:https://github.com/inorindesu/pango-itemizer/blob/master/main.c

程式流程大略是

  1. 把一些原料搬進廠房
  2. 把原料切成恰當的等分
    (utf8界線切割)
  3. 把切割好的原料傳給 pango_itemize 做處理
  4. 把pango_itemize 處理好的 PangoItem 放到出貨區
  5. 收拾
將上面的步驟持續下去直到沒有原料(?),或是原料裡面有蟲(??)才停止

2013年9月7日 星期六

使用 Chart 和 Chart-cairo 繪製統計圖

很多時候我們會想要用圖來呈現我們的資料,畢竟我們對數字的敏銳度不是很高。提到統計繪圖,大部分人會想到 gnuplot 或是 R。對於程式設計人員來說,這代表他們必須寫程式來產生讓 R 或是 gnuplot 繪圖的程式碼,然後再利用作業系統的程式呼叫方法(fork + exec* , CreateProcess)來執行這段程式碼。這樣做不只麻煩(呼叫並管理子程式在某些書甚至會佔去一整章),而且還會犧牲掉不少效能。

Haskell 跟許多程式語言一樣,有人替它寫了圖表繪製程式庫(chart library) Chart。在它的 wiki 裡面可以看到幾個簡單的例子,而且畫出來的圖也挺好看的,更支援 svg, png 等格式的輸出(藉著 cairo 或 diagrams),簡直意圖誘惑人使用。

那些例子裡面沒有說明的部份,包括了中文字使用,字型調整這兩項。所以,我以這兩個項目為主軸,隨便弄了簡單的資料,畫出了相當精簡的圖。主要的程式碼請參考這裡

圖會出來會變成

(我應該放點心思在配色上的..應該是,請看在我肝臟的份上原諒我吧Orz)

使用中文字的關鍵在於設定正確的字型。如果設定的字型沒有中文字,則在應該是中文字的地方會出現方塊圖樣,暗示在該字型中找不到中文字。

Chart 程式庫最特別的地方在於它利用了 lens (不妨 google "Control.Lens" 來找相關的資料) 來讓設定圖表變得(相對的)比較容易。只是對於 lens 我還是第一次使用,所以程式碼裡面難免會有些不漂亮的寫法。如果有幸某大師瞧見了拙作,歡迎不吝指教!

2013年9月6日 星期五

使用 cabal (1.18) 安裝 cairo (改0.12.4.1 beta) 的 haskell binding

Cabal 1.18, 帶有萬眾矚目沙盒功能的 cabal 終於降臨這個世界了!從聽說這版本會導入沙盒功能開始就一直期待到現在,終於出了!或許我們可以準備 cabal-dev 的退休金,讓他回鄉下養老了。關於沙盒功能,有篇文章做了不錯的介紹,歡迎參考。

上面那個其實算是題外話。這裡要紀錄如何修改,讓 cairo-0.12.4.1 (目前,20130906,在 gtk2hs 程式碼倉庫上最新的版本)可以被 cabal 1.18 建置。

首先,要從 gtk2hs 的原始碼倉庫取得最新版的 cairo 原始檔,接著照下面修改:

diff -rN -u old-gtk2hs/cairo/cairo.cabal new-gtk2hs/cairo/cairo.cabal
--- old-gtk2hs/cairo/cairo.cabal        2013-09-06 21:17:11.559949736 +0800
+++ new-gtk2hs/cairo/cairo.cabal        2013-09-06 21:17:11.798946617 +0800
@@ -1,5 +1,5 @@
 Name:           cairo
-Version:        0.12.4.1
+Version:        0.12.4.1.1
 License:        BSD3
 License-file:   COPYRIGHT
 Copyright:      (c) 2001-2010 The Gtk2Hs Team, (c) Paolo Martini 2005, (c) Abraham Egnor 2003, 2004, (c) Aetion Technologies LLC 2004
diff -rN -u old-gtk2hs/cairo/Gtk2HsSetup.hs new-gtk2hs/cairo/Gtk2HsSetup.hs
--- old-gtk2hs/cairo/Gtk2HsSetup.hs     2013-09-06 21:17:11.557949762 +0800
+++ new-gtk2hs/cairo/Gtk2HsSetup.hs     2013-09-06 21:17:11.797946630 +0800
@@ -17,6 +17,7 @@
 
 import Distribution.Simple
 import Distribution.Simple.PreProcess
+import Distribution.Simple.Program.Find (defaultProgramSearchPath)
 import Distribution.InstalledPackageInfo ( importDirs,
                                            showInstalledPackageInfo,
                                            libraryDirs,
@@ -441,7 +442,7 @@
 checkGtk2hsBuildtools :: [Program] -> IO ()
 checkGtk2hsBuildtools programs = do
   programInfos <- mapM (\ prog -> do
-                         location <- programFindLocation prog normal
+                         location <- programFindLocation prog normal defaultProgramSearchPath
                          return (programName prog, location)
                       ) programs
   let printError name = do
diff -rN -u old-gtk2hs/cairo/SetupWrapper.hs new-gtk2hs/cairo/SetupWrapper.hs
--- old-gtk2hs/cairo/SetupWrapper.hs    2013-09-06 21:17:11.558949749 +0800
+++ new-gtk2hs/cairo/SetupWrapper.hs    2013-09-06 21:17:11.797946630 +0800
@@ -6,7 +6,7 @@
 
 import Distribution.Package
 import Distribution.Compiler
-import Distribution.Simple.Utils
+import Distribution.Simple.Utils hiding (moreRecentFile)
 import Distribution.Simple.Program
 import Distribution.Simple.Compiler
 import Distribution.Simple.BuildPaths (exeExtension)

接著

cd /path/to/your/designated/sandbox
cabal sandbox init
cabal install path/to/patched/cairo

注意事項

如果使用

cabal --with-ghc=your-ghc install
的話有機會導致失敗:在建立安裝程式碼的時候,cabal 似乎會使用系統預設的 ghc ,也就是在系統路徑下可以找到的那個 ghc。如果 your-ghc 的版本和 ghc 差太多,而且各自的預設 haskell 套件庫裡面的 Cabal 版本不一致,就會導致很嚴重且難以追蹤的錯誤。

這樣子弄完後應該就可以使用了。為了弄 Chart 以及 Chart-cairo (Chart-diagrams 好像很悲劇的不能畫出中文)結果被 cairo 卡了好幾個小時...

2013年8月19日 星期一

[Fedora] 讓 yum 保留更多的 kernel

最近 Fedora 18/19 的 kernel 升級到 3.10 系列。這樣平常的事情(喔喔!又有新核心升級了!),讓我了解所謂悲劇(好吧其實沒那麼嚴重XD)就是從這些看似日常生活的小事來的。

有天我要使用隨身碟,發現系統無論如何都無法讓隨身碟就緒(是指放到 /dev/sdX1 使可以掛載)。檢視 dmesg 輸出後發現該裝置以某個頻率被重設。搜尋後的結果發現不是電源供應器的問題,而是新發行的 3.10 核心的蟲。這個蟲應該只會影響到某些廠牌,某些型號的隨身碟。

當時已經有個可以解決這個問題 patch 存在,(看了 patch 的感想:僅僅三行的改變,就修復了這個臭蟲。反過來說,僅僅差三行,就讓電腦的隨身碟功能無法運作...)然而,處理作業系統核心對我來說太陌生,所以決定要等 rpm 包裝小組所謂的「上游修復 (upstream)」。這時候我可以用系統內的 3.9 系列核心來擋一下。

2013年8月4日 星期日

使用前請先看說明書喔~

使用任何東西之前,即使自以為熟悉,也要掃描過說明書。如果不恰當的使用這個東西會造成不幸,那就要詳讀說明書。

看了上面的話會不會覺得接著要說的事情很嚴肅?其實這句話是這樣來的,請聽我娓娓道來..

因為有可能會在沒有網路的情況下寫 haskell 程式,很擔心寫到一半發現漏掉了某個程式庫,就只能輕扯頭髮,責罵自己的糊塗...。但我沒有預測未來的能力,很難判斷自己會不會突然需要哪個程式庫..那,如果可以擁有整個 hackage 的話呢(也就是做一個 hackage 的私人 mirror)?

在這樣的構想下,對 hackage 進行探索,發現藉由取得 00-index.tar.gz 即可得到所有 hackage package 存放的位置等珍貴資訊。我可以依據這樣的資料下載整個 hackage 到自己的電腦裡。

對這個程式有興趣的見這裡。這個程式的流程大概是:使用 http-conduit 的 simpleHttp 下載索引檔,剖析它的目錄結構,接著規劃下載(當然也利用 http-conduit 的 simpleHttp),然後全部下載完後做解壓縮測試看有沒有下載錯誤。這樣就結束了是也~為什麼用 http-conduit 的 simpleHttp?它就寫在 http-conduit 說明文件最上端的範例裡,就用下去了。

2013年8月2日 星期五

Parsec 練習:寫個 ass 字幕剖析程式

有些事情很講求緣份,像是遇到不錯且值得去認識的人,或是看到了不錯的程式語言,或是注意到某家餐廳的文宣...。這裡也一樣。

某天在讀 Real World Haskell 的 parsec 那章,有點累想看影片的時候,發現某個 ass 字幕和影片不同步...(差了一秒鐘左右)。隨手找了個叫做 AegisSub 的軟體,正打算安裝起來時發現它需要 wxWidget 2.9 (的樣子),而 Fedora 19 附帶的只有 wx 2.8。正在思考要不要安裝 wx 2.9 的時候突然有種靈光一閃的感覺:「這不是練習使用 hasell parser combinator 的好時機嗎?」,就動工了 :p

2013年7月22日 星期一

用Haskell來食用標籤湯!

網路逛久了總會冒出一些像是「能不能收集某頁面中的所有連結」等想要把某些網頁集合起來做整理的想法。數量少的話,可以手工的做;但數量要是多起來...會很可怕的喔!

這時候就讓自己的程式設計能力上場吧!如果網站沒有提供特別的程式設計界面的話,直接抓取網頁下來分析可能是唯一的方法了。在瀏覽器裡面被排得美美的網頁實際上由 html 這種標記語言所描述,由瀏覽器所呈現。也就是,想要瀏覽器裡面看到的資料,多半可以藉著分析所得網頁的 html 來取得。(利用 javascript 即時生成內容的 Twitter 則是例外。幸好,Twitter 似乎有提供程式設計界面。)

在 Haskell 界最常被提到的 html 剖析器有 HXT 以及 tagsoup。這裡我試用tagsoup寫了一個用來處理簡單的網頁的小程式:見此

寫作這類程式最常不放心的點在於,「網頁改版了,那我的程式就只能去喝西北風了」。有些人會考慮到這點,然後在自己的程式裡面加上一些比較彈性的寫法。然而,我也聽過某些人認為這種擔心是不必要的:到時再重寫就好啦!

反正到時候一定可以解決,不用擔心,先寫再說吧!

2013年7月6日 星期六

cabal, cabal-dev 疑難雜症處理

最近為了要設置隔離的開發環境,使用了cabal-dev。相對於把 haskell 套件安裝到系統區內,cabal-dev 會把套件安裝到另外的地方。這樣做的好處是:

  • 可以確認自己的程式可以在乾淨的環境中被建置起來
  • 有比較大的機會避開套件地獄。
    所謂套件地獄,是指兩個套件依賴了名稱相同,但版本互相衝突的套件的現象。之所以叫做地獄,是因為使用者將因為不知如何是好而狂抓頭皮(或臉頰),並且眼中浮現地獄的景色,故得其名(?)
這裡紀錄了一些遇到的問題以及我使用的解法。

2013年6月28日 星期五

Haskell FFI 的使用(簡單版)

Haskell 雖然強大,Haskell platform 也帶有許多相當好用的程式庫,然而有時候你會發現它少了些我們想用,但目前只在 C 語言程式庫找得到的功能,(例如 podofo 的 PDF 讀寫功能, clutter 的動畫功能。)或者是不滿意某個 Haskell 程式庫的設計(freetype2 package 沒有 high level binding),這時就會需要利用到 Haskell 的「外語功能界面」(Foreign Function Interface)來讓 Haskell 取用 C 語言程式庫所提供的獨家功能。

為了目前規劃中的需要,我試著使用了 FFI 來讓我的 Haskell 程式呼叫我的 C 程式碼:HERE!

2013年6月22日 星期六

安裝第二個GHC在系統中

「新的 GHC 支援我想要的那個XX功能了!」但是系統裡面已經有一個 GHC了?「反正人家就是要最新版的 GHC 啦」?這時候你除了等待你的 Linux distribution 提供更新以外,也可以自力更生,把自己想要的 ghc 及所對應的 haskell-platform 打造出來!

2013年6月17日 星期一

想要離線的 haskell 文件哪裡找?

如果說你可能會有一段時間沒辦法用網路,但又想和 haskell 相親相愛...我們可以準備好編譯器、程式庫等的安裝,但說明文件呢? 沒有說明文件的話可是會讓寫程式變得痛苦不堪!(一定會卡住,一直想著想用的到底是哪個 API,函數原型長怎樣,然後到最後只能打草稿...)

和 haskell 一起的經驗應該是快樂的!所以,我們來試著自己做文件吧!

使用cabal

(出處:見 這裡

如果你相當把握你只會使用某些 package,那就在還可以用網路的時候使用 cabal 來製作文件吧。cabal 預設不會幫你建立文件,所以你必須修改 ~/.cabal/config。打開它,找到以下這行:

-- documentation: False
然後改成
documentation: True
然後重新安裝你想要文件的 package 。須注意重新安裝很多package可能會相當危險。 (這裡 有重新安裝除了 base 以外所有 package 的方法)

想要 ghc runtime library 的相關文件的話,請見下面「下載所有 haskell package」部份的 libraries.html.tar.bz2

使用這個方法建立文件的話,會有個文件索引在~/.cabel/share/doc/index.html

離線建立文件

如果說你沒把握你只會玩弄某幾個 package,而希望可以保險一點的話,那麼就想辦法把整個 hackage 裡的所有 package 都下載下來不就好了?

下載所有的 haskell package

我們會需要下面的所有東西:

  • GHC 文件下載區選正確的版本,然後下載:
    • haddock.html.tar.bz2
    • libraries.html.tar.bz2
    • users_guide.html.tar.bz2
  • Hackage 下的 Getting the raw data,或是 下載整個Hackage archive(使用wget)
如果下載的是 Getting raw data 中的 00-archive.tar, 則:
mv /path/to/00-archive.tar /tmp
cd /tmp
mkdir hackage
cd hackage
tar -xf ../00-archive.tar
每個對應的 haskell package 就會存在/tmp/hackage/PACKAGE_NAME/VERSION/PACKAGE_NAME-VERSION.tar.gz

建立文件(相依套件已存在)

文件下載好後,我們利用下面的步驟來建立文件

# in /tmp
mkdir build
cd build
tar -xf ../hackage/array/0.4.0.1/array-0.4.0.1.tar.gz
runhaskell Setup configure --builddir=./array-build --user
runhaskell Setup build --builddir=./array-build
runhaskell Setup haddock --builddir=./array-build
# 完工\^o^/ ,去./array-build/doc 找做好的文件
# 想順便安裝的話...
runhaskell Setup install
# 安裝完後,也可以在 ~/.cabal/share/doc 下找到做好的文件。
另外一種方法:
mkdir build
cd build
tar -xf ../hackage/array/0.4.0.1/array-0.4.0.1.tar.gz
cabal configure
cabal haddock
# 此時文件會在 dist/doc/html 中
# 如果想要安裝起來,那就再執行:
cabal install

如果相依套件不存在,就找到相依套件,然後使用這裡的步驟把所有的相依套件安裝起來吧!

建立文件(相依套件未存在且不想安裝)

假如你不想安裝建置好的程式庫(?),那麼你可以考慮利用這裡的方式,暫時把相依套件建立在某個暫存區內。

假設我們想安裝zip-archive, 結果發現:

$ runhaskell Setup configure --builddir=../build --user
Configuring zip-archive-0.1.3.4...
Setup: At least the following dependencies are missing:
digest >=0.0.0.1, utf8-string >=0.3.1
$ 
那就試試這裡的步驟吧!
(相依性資訊記載於下載下來 package 的 tar.gz 中的 .cabal 檔中的 Build-depends 內)

# in /tmp
$ mkdir build
$ cd build
$ # 解開包裹
$ tar -xf ../hackage/utf8-string/0.3.7/utf8-string-0.3.7.tar.gz
$ tar -xf ../hackage/digest/0.0.1.2/digest-0.0.1.2.tar.gz
$ tar -xf ../hackage/zip-archive/0.1.3.4/zip-archive-0.1.3.4.tar.gz
$ # 設定暫存位置
$ mkdir packages # package 暫存區
$ mkdir tmp # build 暫存區
$ # 設定暫時 package 註冊區
$ ghc-pkg init package-db
$ # utf8-string 0.3.7
$ cd utf8-string-0.3.7/
$ runhaskell Setup configure --builddir=../tmp/utf8-string\
 --prefix=`pwd`/../packages --package-db=../package-db
Configuring utf8-string-0.3.7...
$ runhaskell Setup build --builddir=../tmp/utf8-string
Building utf8-string-0.3.7...
Preprocessing library utf8-string-0.3.7...
# 編譯過程,略
$ runhaskell Setup haddock --builddir=../tmp/utf8-string
Running Haddock for utf8-string-0.3.7...
Preprocessing library utf8-string-0.3.7...
Warning: The documentation for the following packages are not installed. No
links will be generated to these packages: rts-1.0
Haddock coverage:
 100% (  8 /  8) in 'Codec.Binary.UTF8.String'
  94% ( 16 / 17) in 'Codec.Binary.UTF8.Generic'
  89% ( 24 / 27) in 'Data.String.UTF8'
  82% ( 14 / 17) in 'System.IO.UTF8'
  14% (  1 /  7) in 'System.Environment.UTF8'
 100% ( 17 / 17) in 'Data.ByteString.UTF8'
 100% ( 17 / 17) in 'Data.ByteString.Lazy.UTF8'
Documentation created: ../tmp/utf8-string/doc/html/utf8-string/index.html
$ runhaskell Setup install --builddir=../tmp/utf8-string
Installing library in
/tmp/build/utf8-string-0.3.7/packages/lib/utf8-string-0.3.7/ghc-7.4.1
Registering utf8-string-0.3.7...
$ cd ..
$ # digest 0.0.1.2
$ cd digest-0.0.1.2
$ runhaskell Setup configure --builddir=../tmp/digest --prefix=`pwd`/../packages --package-db=../package-db
Configuring digest-0.0.1.2...
$ runhaskell Setup build --builddir=../tmp/digest
Building digest-0.0.1.2...
Preprocessing library digest-0.0.1.2...
[1 of 2] Compiling Data.Digest.Adler32 ( ../tmp/digest/build/Data/Digest/Adler32.hs, ../tmp/digest/build/Data/Digest/Adler32.o )
[2 of 2] Compiling Data.Digest.CRC32 ( ../tmp/digest/build/Data/Digest/CRC32.hs, ../tmp/digest/build/Data/Digest/CRC32.o )
In-place registering digest-0.0.1.2...
$ runhaskell Setup haddock --builddir=../tmp/digest
Running Haddock for digest-0.0.1.2...
Preprocessing library digest-0.0.1.2...
# 建立文件訊息,略
Documentation created: ../tmp/digest/doc/html/digest/index.html
$ runhaskell Setup install --builddir=../tmp/digest
Installing library in
/tmp/build/digest-0.0.1.2/../packages/lib/digest-0.0.1.2/ghc-7.4.1
Registering digest-0.0.1.2...
$ cd ..
$ # zip-archive
$ cd zip-archive-0.1.3.4/
$ runhaskell Setup configure --builddir=../tmp/zip-archive --prefix=`pwd`/../packages --package-db=../package-db
Configuring zip-archive-0.1.3.4...
$ runhaskell Setup build --builddir=../tmp/zip-archive
Building zip-archive-0.1.3.4...
Preprocessing library zip-archive-0.1.3.4...
[1 of 1] Compiling Codec.Archive.Zip ( src/Codec/Archive/Zip.hs, ../tmp/zip-archive/build/Codec/Archive/Zip.o )
In-place registering zip-archive-0.1.3.4...
$ runhaskell Setup haddock --builddir=../tmp/zip-archive
# 建立文件訊息,略
$ runhaskell Setup install --builddir=../tmp/zip-archive
Installing library in
/tmp/build/zip-archive-0.1.3.4/../packages/lib/zip-archive-0.1.3.4/ghc-7.4.1
Registering zip-archive-0.1.3.4...

這樣就完成了呢!這時候文件會存放在/tmp/build/packages/share/doc/裡面,然後你就可以開始閱讀他們了!

2013年6月16日 星期日

解壓縮zip檔案:當中文字變成亂碼之二

前情見上一篇。 弄了一天多,總之弄出了可以用的東西(在這裡,想要看程式碼的人,歡迎光臨!)。

2013年6月15日 星期六

解壓縮zip檔案:當中文字變成亂碼

最近學習haskell中,想要拿幾個文字檔來練習IO以及資料處理。首先試著找"open data taiwan",想看有沒有台灣政府提供的政府資料。找著找著,找到了經濟部能源局的資料。點了第一個下來,開始準備解壓...檔名是亂碼Orz

雖然可以猜得出檔名應該是「國際原油價格.csv」,但對於處理內有中文檔名的壓縮檔已經不是第一次了。我想要一口氣解決它!(然後haskell之夜就泡湯了Orz,詳下)

搜尋發現了一些解決方案,包括了「unzip -O」(我的unzip沒有這個選項),「LANG環境變數+7za」(出來還是亂碼)。我想要一個可以解壓縮,然後一邊更改檔案名稱編碼的解壓縮程式,不過目前看起來能夠符合我條件的解壓縮程式似乎不存在,所以只好自己來做一個簡易版的。

我首先考慮了正在練習的haskell,但是,就在我腦袋閃過了python的解決方法後,我決定先用python試一下,然後...就結束了?(程式碼見此

那個python的解決方案使用了python 2.x,而不是python3。仔細一瞧,python3 的 zipfile 模組傳回的檔名字串似乎沒辦法轉換成原本在zip檔中的原始字串(raw string,原汁原味的那個字串),所以沒辦法像在python 2.x裡那樣子做編碼轉換。

鑑於python沒機會了,我想依賴haskell看看。在hackage中搜尋之後,我猜使用zip-archive, iconv,再配合上bytestring這三個package應該就可以完成目標了:使用Data.ByteString.Lazy.Char8 的 pack, Codec.Text.IConv 的 convert 應該就可以順利的進行轉換。現在有點晚了,明天再來試試看。

每次看到別人說 haskell 只是學術界教授們在用的程式語言,我都覺得很傷心:明明有那麼多的 package,這麼有趣的語法...。因此,我衷心的希望我可以利用這次機會來證明 haskell 不只是象牙塔裡的玩具,因此我會加油的!

2013年6月1日 星期六

所謂的執法

很令人訝異的,最近台灣發生的一些大事都和執法有關。

首先來說說已經有點久的廣大興28號漁船攻擊事件。這起攻擊事件喚起了許多國人的愛國意識,並且理性的(我們不過把軍艦開到經濟海域逛幾圈對吧?)追求屬於我們的那份正義。

簡單的說,有個漁民在有爭議的經濟海域捕魚,被菲律賓海巡隊釘上並遭到強烈火力的攻擊,漁民洪石城先生在此攻擊中不幸喪生。廣大興28號回港後,我國政府給菲律賓政府72小時 (也就是三日)通牒,希望菲國政府為此事件道歉,並且啟動公平的調查;然而,未把台灣當成一個國家來看待的菲國打算敷延了事,讓台灣人民群情激憤。在夾帶民意的支持下, 我國政府行使了主權國家才有的權力,祭出了許多項包括經濟以及外交方面的制裁,並且(稍稍的)利用軍隊施壓。此時國際輿論對於此事件大多偏向憐憫菲律賓,所幸在眾多鄉民們的努力之下 ,國際輿論終於看清菲律賓政府執法過當之事實。現在,調查的結果強烈的指出菲國海巡隊執法過當,濫用火器才導致本次事件的發生。

這個事件起初不是相當明朗。例如說,我們不知道漁船有沒有試圖衝撞海巡隊的鐵船(雖然看就知道..嗯..),也不知道漁船有沒有不服對方海巡隊的指示(客觀來說,只憑著我方漁民的說詞 是不夠的。當然我相信他們的清白),然而事實很清楚:就算我們的漁船真的犯下了一些錯,菲國執法單位,依據國際法,也沒有權力使用軍用等級的槍械來掃射手無寸鐵的漁民。

接著的兩個事件都是本週內的。

第一個是智慧財產局(智財局)宣佈要實施的「封鎖境外侵權網站」的措施。依據該局的說法,若某境外網站有「一望即知」的侵權現象,則將在邀集各方人士開會後利用IP協定(或從DNS移除該網站網址的對應IP)封鎖該網站。此措施為人詬病的地方是,若該法案通過,則將會賦予政府機關未經法院判決而得以限制人民閱聽目標網站的權利。此外,此法案等於是為了守護少數人之利益,而侵犯大眾的,受憲法保障的祕密通訊自由。在美國,利益團體邀請國會議員推行類似的法案SOPA(和台灣的差別?封網站前要先經過法院。)受到各界,包括白宮、維基百科、以及世界各大網站的強烈反對,最後在國會中難產。

我相當的希望這個無論在技術上、法理上都站不住腳的法案不要通過。一旦這個法案通過了,我國的言論自由將會嚴重的後退。到時有心人士會不會利用這個法案來封鎖我們喜愛的境外網站呢?(莫須有的侵權)我們以後還可以下載GNU/Linux, 看CNN或經濟學人嗎?(相信大家都懂的>_^)即使封鎖網站會經過法院的審理,大家都知道因為侵權材料而封鎖一個IP,就跟有人擺攤賣假包包就命令整條街道禁止營業一樣的扯。

最後是非常令人傷感的,一位好醫師(願意投身於愛滋病人長期照護的醫師現在已經不多了)因為一個「只」喝了半瓶伏特加,自以為沒有醉的人給撞成重傷了。該醫師的指導老師柯文哲醫師除了心痛外,也呼籲類似的事件(也就是酒後駕駛)不要再發生了。現在各界人士都希望奇蹟可以出現,讓這位醫師得以回來繼續實現她的夢想。

雖然這個事件描述是三者最短的,但也是最令人感到哀傷的一個。這個事件也讓我聯想到葉少爺酒駕事件,以及那個破碎的,再也回不來的家庭。

此時立院修法通過加重酒後駕駛的刑期,然而修法後的條文也不過就是加重了刑期而已。那些酒後開車的人沒有顧及他人的生命(明知道開車上路會不穩,會撞到人),開車上路已經可以說是殺人未遂了;如果真的很不幸撞死了人,那怎麼不用殺人罪去法辦呢?這樣至少比本次事件的「三萬元交保」還要符合比例原則!

菲國政府願不願意把兇手引渡來台灣受審,基於國際情勢,是個未知數,但至少我們現在已經還漁民一個清白了。之所以可以討論此事件,並在菲國利用國際輿論來抹黑我國的同時由許多偉大的鄉民串連在國際上發聲,憲法賦予我國的言論自由絕對功不可沒(沒了這個我們可不能批評我們的政府軟弱無能)。然而,我們可貴的言論以及祕密通訊的自由有可能會受到賦予制裁局封鎖網路權力(為了保障少數人)的惡法威脅,在此同時,我們的法律卻又無法保護許多認真的,默默為了夢想而付出的人們。

我不禁想,除了流眼淚之外,我還可以做什麼...

2013年5月24日 星期五

文件撰寫工具的探索:要定下來了嗎?

之前試驗過xelatex的使用,也說過還不錯,但那時心理就覺得要「反璞歸真」,選擇繼續往plain xetex的方向來學習。這樣的好處是版面的安定性,以及整體的簡潔:不需要依靠大量的latex package就可以完成大部分的排版工作。的確,實際上來說,只要做些簡單的設定,xetex甚至可以做簡單的中文斷行工作而不需要使用xeCJK之類的package(當然,要美觀的版面,還是得用xeCJK)。眼看著xetex將會成為我的親愛的說明文件排版工具...結果它似乎沒辦法很完美的展示程式碼..Orz(附帶一提,xelatex可以用listing這個package來放入程式碼,而且還附有著色的功能喔!)在發現這個事實的同時,我同時也被稱作「輸出格式」的鬼附身,不斷的改著文件的輸出格式,已滿足內心對於版面美觀的小小渴望。(像是「我覺得應該要再往上1pt」「行距好像怪怪的(拿起尺)」等等)就在這時候我想起DocBook。

DocBook是一個xml衍生出來的標記格式(markup language),利用這個標記語言,寫作者可以很輕鬆的表達一份技術文件的內容。由於輸出文件的格式取決於選用的處理程式以及樣式表,因此docbook有效的把內容以及格式的處理分隔開了。這樣的分隔是DocBook設計者的好意:把文件的內容及格式區隔開來後,作者們應該就會把精力放在內文的寫作,而不是排版上了吧?很可惜的是,上一次在考察的時候,我忽略了他們的善意,導致了現在這樣的結果。

2013年5月16日 星期四

利用lua帶給brainf*k編譯器無限美好的未來(XD)

打完這標題我都笑了XD
之前提過我一個作品,brainf*k(下稱bf)直譯器。它可以讀取一段bf程式並且立刻把執行的結果告訴你。當時的設計把底層和直譯器界面分離,所以只要建立編譯器的界面就可以完成一個編譯器了。當時相當有野心的畫了塊餅:做一個超級有彈性的編譯器,讓它可以把bf程式輸出成各種不同的形式。
(完成品請見這裡

2013年5月2日 星期四

從字型檔中取得文字的輪廓

我承認我對字型檔有非常特別的愛好:打開一個字型檔,欣賞著它美麗的字體,就可以讓我開心一段時間。有些字體相當的工整,很適合用來製作美麗的書本或報告;有些則相當的具有藝術氣息,如果放在海報或藝術作品上面會有相當好的效果。總之在我眼中,那些一個個的字體就像是藝術品一般的迷人。有一些字體甚至被設計成裝滿形狀特別的符號的箱子,等你拆開來好好的一個個放大來欣賞。

2013年4月28日 星期日

把二次Bézier曲線轉換成三次Bézier曲線

在看FreeType的文件時(Glyph convensions),發現 TrueType中的字型使用二次Bézier曲線,而其他的幾乎都使用三次Bézier曲線。那如果想要使用的曲線繪製軟體只支援三次曲線的話怎麼辦呢?

cairoMoon: 利用C語言提供功能給lua使用

好久沒有寫程式了呢XD
說實話我一直掛記著BF編譯器的實行,也不斷想著要怎麼做到還可以接受的程度。不過,我想先作個小東東來練習下。

2013年4月14日 星期日

超級感人殭屍影片

如果你知道你的意識只剩下三個小時,而你的小孩在旁邊,那你會做什麼?有個Youtube短片正好描述了這個故事。

2013年4月5日 星期五

合字:把一個以上的字符組合起來的藝術

合字(ligature)是指,在某些情況下,一個或以上的字符會以不同於獨立字符排列在一起的方式組合起來,形成一個新的圖樣。舉例來說,中文的「招財進寶」寫在春聯上的樣子就是一種合字;阿聯國際航空公司的公司圖案(logo)上面也有一個很漂亮的合字(見左上角紅框);有許多字體可以把拉丁文中的ff和fi排成比較漂亮的形式(見此。)。這些合字讓人看起來很舒服,而且有一種在欣賞藝術品的感覺!

有些合字比較少會在文件中使用,而有些合字則是太常被使用,而讓人沒有留意到他的存在。如果手上有本英文雜誌或英文書,就有機會可以找到fi, ffi的合字。

2013年3月28日 星期四

liblua.so的製作

從lua官方下載到原始碼之後,手動編譯它,然後就會有lua, luac, 以及liblua.a三個二元檔,以及一些header和文件等..等等,少了什麼的樣子。親愛的動態連結程式庫勒??

難不成lua沒辦法做成動態連結程式庫?直覺上來說,不可能。(光是有這個想法就讓我覺得自己..)Makefile裡面沒有寫不代表生不出來,更何況提供precompiled binary的網站也有提供動態連結程式庫,所以這樣的東西一定可以被做出來。

2013年3月24日 星期日

透過lua提供擴充功能的機會

玩過許多軟體的人或許都會對那些提供功能擴充界面(外掛界面)的軟體有相當的印象,例如emacs, firefox, notepad++, WoW, Homeworld2等。這些軟體如了原本就有的功能以外,由於擴充界面的存在,讓許多有創意有能力的大眾得以把程式改良到接近自己所喜愛的樣子;而這些被製作出來的外掛則反過來增加了程式的知名度,讓程式得以接觸更多的人。

2013年3月23日 星期六

試用xelatex

基於想要選擇一個適當的文件製作工具的心情,我決定試用名聞遐邇的latex。

Latex具有悠久的歷史(比我還要老呢!),一般來說用在科學文件,但理所當然的也可以用在任何文件上面。總之如果想排出精美的文件,就可以讓latex幫你喔!

2013年3月20日 星期三

寫文件要使用什麼工具?xelatex以及Docbook超簡介

在我心中,一個好的程式是那些不需要讀說明書就可以使用到它七成以上功能的那些。這類的程式多半會有相當精巧的設計,讓人得以輕鬆上手。然而,對大部分程式來說,一般人可能只能參透這個程式最主軸的幾成(三到五成吧)功能。這樣子其實是相當可惜的不是嗎?天生我才必有用,程式設計人員不可能會把沒有用的功能放在自己的程式裡面(「會心一笑」和「炫耀」在這裡都算是有用的功能)。

2013年3月18日 星期一

Brainf*k: 超精簡程式語言之口譯篇

偶然的機遇下,我認識了一個超精簡的程式語言brainf*k(下稱BF)。這個程式語言的特性是,只有8個指令,卻被認為可以完成任何的計算(似乎是Turing-complete特性。),正所謂「麻雀雖小,五臟俱全」。

也因為這個程式語言的簡潔性(每個操作均由一個字元表示,而且沒有運算子順序等等的問題...),讓我想:不如就做一個BF直譯器吧!依據當時我腦袋瓜子裡的規劃(「用一個main直接解決它吧!」),應該只要一個下午,頂多再加上一個晚上就可以完成了吧?

2013年3月9日 星期六

Harfbuzz:複雜文字排列的好幫手

經常被使用在OpenGL遊戲設計上的freetype2不只可以依照所選定字型檔來將文字點陣化,點陣化的文字接著被使用在OpenGL場景中。上面所描述的是當一個OpenGL軟體要使用文字的時候的最常見用法,也是許多線上教學會教各位的方法。

然而,freetype2所提供的layout engine無法使用OpenType所提供的許多更進階的文字繪圖指示(例如說某些阿拉伯文字)。這樣子的功能必須由更為專業的layout engine來代勞,像是pango。

仔細調查後會發現pango的相關功能是由harfbuzz所提供的。也就是,我們可以繞過又大又重的pango(使用pango會增加對glib的依賴性),直接調用harfbuzz來進行複雜文字繪圖的工作。此外,直接使用harfbuzz的程式不只可以利用系統字型(需要直接指定系統字型的檔案位置。可以用fontconfig來解決這個問題),還可以使用軟體自帶的字型檔案。

由於harfbuzz沒有文件檔案,範例檔案又寫得相當之高深(看完原始碼中util/hb-shape.cc之後的感想是:作者大人實在有夠強大!),所以只好花時間在網路上不斷的看人討論的文章。

在和harfbuzz奮鬥三天(左右)之後,找到了以下的範例檔案:

而且自己動手做了一個小程式,放在Github

我使用的流程和上面所列出的範例檔不同:首先,我把字型檔案利用mmap整個讀取進記憶體,接著利用harfbuzz載入它,用freetype2來繪製字型,最後由libpng把輸出的圖形放到png圖檔中。

當我看著由這個小巧的自製小程式所繪出的精美阿拉伯文字時,我整個人都飛躍了起來,超開心!

2013年3月8日 星期五

順序很重要:gcc library參數的順序

今天呢,想說來看一下lua好了。Lua是一個在許多遊戲中當作scripting language的程式語言,為這些遊戲提供了不小的擴展性。首先,lua可以讓遊戲在不重新編譯的狀態下更有彈性的更改參數;其次,lua提供了一個讓玩者自訂遊戲的管道(像是製作新道具等)。

提供自訂能力的lua必須由另一隻程式來驅動。也就是,我可以做出一隻C語言的程式,讓該程式與lua程式庫連結,然後載入並執行lua的程式碼。

2013年3月3日 星期日

使用OpenGL畫圖片(png圖檔)

前情請見此文
簡單的說,我希望可以利用OpenGL來作2D繪圖,在上篇文章中已經畫出了有色彩的三角形,這次的目標是把圖檔畫出來。
本文介紹的程式使用了材質貼圖、indexed VBO以及讀取png圖片並形成材質的技術。

文中的程式碼均放置於Github中。

以下是簡單的筆記摘要:

2013年3月2日 星期六

使用Freetype2來繪製單一字母

對於一個畫家來說,OpenGL是畫家的手,只能呈現畫家腦袋裡面已經存在的靈感。對於想利用OpenGL來繪製場景的人來說,場景中所出現的人物、圖片、文字等都需要事先準備好(無論以何種形式)。

對於一個遊戲來說,遊戲中所要使用的圖片需要事先畫好;遊戲中所要用的文字需要先寫好。然而,對於以OpenGL為作圖元件的遊戲來說,文字的部份是一個嚴峻的挑戰:OpenGL,和許多提供繪圖功能的元件(Qt, Cairo...)相比,沒有提供文字繪製的功能(連一丁點都沒有!!)

因此,想要利用OpenGL作為繪圖工具,但同時需要呈現文字的話,有幾種方法:

  • 把文字事先以其他的軟體製作成圖片,然後利用材質貼圖把字貼上去。
    本方法對於使用拉丁字母的語言(如英文)來說是最簡單的解決方法,但無法滿足想要放眼世界的野心。
  • 利用其他的元件,把文字繪製出來,再利用材質貼圖把動態繪製的文字圖貼上去。
    缺點就是比較麻煩,也增加了相依性(需要其他可以繪製文字的程式支援)

製作「文字圖」以供OpenGL的方法相當多。可以用Qt, Gtk+, pango, cairo...,但它們不只稍微大了點,而且還無法直接使用所指定的字型檔而必須使用已經安裝在系統中的字型。對於一個想要使用作者自選字型的可攜式軟體來說還需要其他的解決方法。

對於上面囉哩囉唆說了一堆的問題,目前最受歡迎的自由軟體解法是Freetype2。Freetype2是一個小巧的字型程式庫,可以讀取許多格式的字型,並且提供了點陣化(rasterization)以及簡單的輔助文字排列功能。Freetype2所提供的功能足以應付地球上大部分(八成吧)文字排列的需求。

基於我對於各種字型的著迷以及對此主題的興趣(我超喜歡畫圖的喔!),做了一組小小的程式來展示如何利用Freetype2來把單一字母繪製出來。請見這裡

由於對OpenGL還不甚了解(還在學習如何使用材質貼圖..)所以這組程式把所指定的文字輸出到PNG圖檔中。

使用方法

利用cmake來編譯:(記得對build_dir和source_dir作適當的替換)

$ mkdir build_dir
$ cd build_dir
$ cmake source_dir
$ make
接著,假設你想要繪製「好」,則:
$ ft2_char_cairo 好 /usr/share/fonts/wqy-microhei/wqy-microhei.ttc > /tmp/1.png
那麼,「好」字就會被輸出到/tmp/1.png了。

注意事項:

  • 想改變字的色彩?請找到如下的程式碼:
    # define RED (192)
    # define GREEN (255)
    # define BLUE (192)
    void render_glyph_to_stdout(FT_GlyphSlot slot)
    
    然後把RED, GREEN, BLUE括號中的數字改成你想要顏色的RGB元素。
  • 如果您使用Windows,則由於Windows的shell預設不是utf-8,所以在指定中文字可能會有問題。
  • 另外,如果所指定的字型檔中沒有這個字元的話,字就不會被畫出來。

2013年2月24日 星期日

Hello OpenGL!

心血來潮想學習使用OpenGL(很久以前就想要使用OpenGL來作2D繪圖了!),便上網隨手搜尋相關的教學。(雖然印象中有一個不錯的NeHe教學,但怕它已經過時了,所以..還是找一下囉)。很快的就找到了opengl-tutorial.org這個教學網站。和一般的教學不同的地方在於它所選用的GL utility library不同。NeHe的教學採用的是glut,而opengl-tutorial使用了glfw(主要), glew以及glm。此外,opengl-tutorial所教是比較新的OpenGL 3.3 core profile。

簡單的說,core profile和以前所使用的OpenGL的差異(OpenGL 3.3 的compatibility profile)在於fixed pipeline的存在與否。Fixed pipeline是glVertex, glVertexPointer, glColor, glTexCoord等所提供的繪圖動作,相對於我們利用shader(給GPU跑的程式)來定義的繪圖動作來說是沒有彈性的(故稱fixed pipeline)。

總之看完教學1~4之後,我決定動手做做看。

2013年2月22日 星期五

人體奧秘之Code Fred

今天玩到一個很有趣又有教育意義的遊戲:Code Fred。(想在Kongregate玩請點這裡)這是一個由芝加哥科學與工業博物館所製作的遊戲。

遊戲中,玩者會跟著遊戲的指示,啟動許多人類與生俱來的緊急應變措施,例如心率與呼吸頻率的上升、傷口的修補等。藉著和遊戲一起幫助Fred逃離某個詭異的森林,玩者也會了解到人類(也就是玩者本身)的身體所帶有的許多神奇力量(無誤)。

遊戲結束後,有沒有驚訝於自己身體所能做到的事情呢?身體默默的為了各位能夠享受人生而默默付出,所以記得要善待它,讓它可以和你攜手走過一生!

2013年2月19日 星期二

從Project of the month到如何下載wikipedia上的圖片

今天早上在半夢半醒的狀態下偶然看到Sourceforge的「本月計畫」(Project of the Month)為Kiwix。根據介紹,它是一個可以設計來讓使用者可以在離線的狀態下閱讀維基百科。這樣的設計相當棒:有電腦,無聊,但又沒有網路,就可以靠它來消磨時間了!更棒的是,對於居住在網路不是這麼普及地區的人們來說,這可說是一大福音!

2013年2月18日 星期一

與Git的近距離接觸

托新酷音輸入法內含的字庫(原始碼中的phone.cin),「掉落方塊打字」遊戲已經有個可以使用的雛型了。(見此

這個小遊戲是個人近期內較大的作品,為了小心起見,使用了版本控制系統git,利用自己粗淺的版本控制經驗來保存整組程式碼。雖然說是開發初期,但我除了commit, status, push, log, diff之外沒有在利用到git其他的(神奇)功能了。瞧瞧git的manpage,就知道git一定是被我大材小用了。有人說和朋友相處的第一部就是好好了解那位朋友,因此決定花時間學習git的使用技術。嗯,稍微進階的那幾種。

2013年2月9日 星期六

革命尚未成功

革命尚未成功,請各位多加努力。

在農曆新年前夕用這段話開頭的理由是,龍年裡發生了很多故事,但我們還沒有看到它們的結局。總而言之,今年有很多事情會是去年的延續。

2013年1月27日 星期日

利用libchewing讓程式得以接受注音輸入

最近有很多機會可以讓我回想以前的事情。首先是歐巴馬總統的就職典禮(今年和四年前。附帶一提,他的就職演說相當的感人),馬總統的黨主席選舉爭議(想到之前選總統時也修改黨章),釣魚台主權爭議(讓某些媒體想到了世界大戰前夕),美國的槍枝管制爭議,Fedora 18的發表...每一個項目的背後都有個可歌可泣的故事。

我想到很久很久以前有一個打字遊戲:文字從天而降,而玩者要把在方塊上面的字打出來,讓方塊消失。現在我想要把它做出來回味一下。

2013年1月9日 星期三

關於最近的印度女大學生命案

去年12月中,有個印度的女大學生和朋友去看電影,在回家的路上慘遭毒手,送醫後,雖然寫下了「我想活下去」,但仍然在幾天之後不幸死亡。有些報導對於這位女大學生的悲慘遭遇有比較清楚的描寫。我看了那個報導之後覺得相當的難過。身為文明古國的印度境內竟然還有這樣令人髮指的事情發生。

2013年1月3日 星期四

電影觀後感:Eagle Eye

今天要分享的作品是一部2008年的電影Eagle Eye(中譯為鷹眼)。如果從片名來看的話,整個主題看似要探討政府以反恐為名而對小老百姓們所做無孔不入的監控。

蘋果日報與一個家庭的夢想

最近注意到蘋果日報的頭版有這個新聞:勇敢媽:前面有無限希望。裡面在講蘋果日報滿足一個單親家庭夢想的故事。

如果聽到蘋果日報,一般人應該會想到描寫相當寫實的社會新聞、充滿了莫名口味的娛樂版、爆料文化、以及最近幾年來可以看到的「案發現場模擬圖」。自我開始翻看蘋果日報以來,一直很遺憾的就是那個沒有內容卻佔去不少版面的娛樂版了。總覺得這種事情不應該佔去如此龐大的版面。

即使如此,蘋果日報仍然有深深吸引我的地方。首先是它的爆料文化。雖然說蘋果日報在很多情況下似乎沒有尊重當事人隱私(尤其是藝人的八卦:某丙要和某丁一起在哪裡過夜對我來說都不重要,所以不必要為了這種新聞去守候在人家門口),它揭露了某些一般媒體無法,或者是沒有膽量去報導的事件,像是政治弊案、賄選等。對於蘋果日報所持有的那個勇氣,我由衷的感到相當敬佩。

另外一個吸引人的地方是有時會被刊載的急難家庭的消息,以及捐款資訊。這個部份的內容,以及捐款的管理,是由蘋果日報慈善基金會(見此)所主導的。上面所列出的報導應該就是該基金會的成果之一吧!

民眾的捐款會由基金會直接交給那些急難家庭。在我的印象中,大部分的事情就這樣結束了。很少可以看得到像上面一樣的特別報導。總之,看到報導中小姐弟完成願望的快樂,以及母親的「加油」,我覺得我分到了一些幸福的糖漿。吃起來很香甜、很美好,甜到眼淚都要掉出來了..

看新聞的時候我最喜歡看的就是這樣的新聞了,真心的希望蘋果日報的版面可以多一些這樣子的溫馨故事(不管是不是蘋果日報慈善基金會主導的),少一些重口味新聞。讓讀者分享到多一些溫暖,也算是一種善事吧!

附帶一提,希望將蘋果日報買下來的那些商人們,除了不要妨礙新聞自由之外,更希望你們不要把蘋果日報慈善基金會,蘋果日報中最美好的一部分,收起來。

2013年1月1日 星期二

(Linux)不斷電緊急重新啟動的方法...有嗎?

發這篇文的時候剛跨完年,祝福各位讀者新年快樂,心想事成喔~

之前有一陣子,我發現nouveau好像怪怪的。
首先介紹一下nouveau(是法文喔~)。它是Linux下面一個知名的,針對NVIDIA顯示卡的自由驅動程式。這個驅動程式可以讓Linux的使用者們享用NVIDIA顯示卡上面的3D加速功能。很遺憾的是,這個驅動程式還沒有包括GPGPU的驅動能力。