廣論原文資料結構

 

末學在設計此資料結構的時候,稟持著幾個原則,一是此資料必須易於修改,二是此資料必須讓人一眼就知道如何修改,換句話說,此資料結構盡可能符合人類閱讀習慣,複雜的格式轉換盡量使用程式來解決。廣論原文的資料位於TheoryData.java中,之所以不用App資源(Android Asset)的方式,是因為Android早期的Asset不支援讀取UTF-8格式的檔案內容,所以只好改以程式碼的方式設計,結構範例如下:

/*===========================第 2 頁===========================*/
" 故離智者歡喜道 圓滿教要勝教授 見已釋此大車道 故我心意遍勇喜\n"+
" 諸有偏執暗未覆 具辨善惡妙慧力 欲令暇身不唐捐 諸具善者專勵聽\n"+
"  此中總攝一切佛語扼要。遍攝龍猛無著二大車之道軌。往趣一切種智地位勝士法\n"+
"範‧三種士夫‧一切行持‧所有次第‧無所缺少。依菩提道次第門中‧導具善者趣佛地理‧是謂\n"+
"此中所詮諸法。\n"+
"  此中傳有二派釋儀。勝那蘭陀諸智論師‧許由三種清淨門中‧詮釋正法。謂軌範語淨‧\n"+
"學者相續淨‧所說法清淨。後時止迦摩囉室囉‧聖教盛行‧彼諸智者‧則許三種而為初要。謂\n"+
"正法造者殊勝‧正法殊勝‧如何講聞彼法規理。今於此中‧應如後釋。\n"+
"<b><s> 由是菩提道次引導分四‧<n>一</n>為顯其法根源淨故開示造者殊勝‧<n>二</n>令於教授起敬重故開示其</s></b>\n"+
"<b><s> 法殊勝‧<n>三</n>如何講聞二種殊勝相應正法‧<n>四</n>如何正以教授引導學徒之次第。  今初</s></b>\n"+
"  總此教授‧即是至尊慈氏所造‧現觀莊嚴所有教授。別則此之教典‧即是菩提道炬。故\n"+
"彼造者‧亦即此之造者。彼復即是大阿闍黎勝燃燈智‧別諱共稱勝阿底峽。\n"+
"<b><s> 其殊勝分三‧<n>一</n>圓滿種中受生事理‧<n>二</n>其身獲得功德事理‧<n>三</n>得已於教所作事業。  今初</s></b>"

 

段落切齊

 

相較於紙本廣論中所呈現的原文,會發現到紙本廣論每一行的段落位置幾乎工整,不會像上面的資料結構每一行長長短短參差不齊,主要是因為在廣論原文中的標點符號是不佔空間的側標,而一般數位資料結構標點符號是佔一個字元長度的字元,所以標點符號必須像紙本廣論一樣做成側標,才能讓使用者在數位工具學習上與紙本廣論有一致的體驗。

為了達到上述的目的,程式在處理廣論原文時使用下列的步驟:

  1. 從每一行的廣論原文中刪除標點符號,並記錄該符號的位置與類型(逗號、句號)。
  2. 印出該行不含標點符號的文字。
  3. 根據第一步所記錄的位置,在該位置畫上實心圓(逗號)或空心圓(句號)。
  4. 重複上面三點,直到整頁列印完成。

除此之外,會發現標題的部分仍然過長,如第九行的「由是菩提道次引導分四一為顯其法根源淨故開示造者殊勝二令於教授起敬重故開示其 ...... 引導學徒之次第。  今初」,檢視紙本廣論原文會發現標題的部分字型縮小並變為粗體字,為還原該格式,末學定義了二種標籤:

<s>...</s>: 小字型,用於論文的標題部分。
<b>...</b>: 粗體字,用於論文的標題部分。

小字型的部分,在廣論App中是設定為主要字體的90%大小呈現,因為牽涉到使用者雙指縮放字體功能,主要字體經使用者縮放後,再根據縮放後的主要字體大小決定小字體的大小。

最後,在標題中,列表數字不易分辨,常有二個數字連在一起的狀況,如「由是菩提道次引導分四一為顯其法根源淨故開示造者殊勝」,為令使用者易於辨別,末學在數字列表的部分也加上顏色區別,讓使用者更容易閱讀,於是定義了數字標籤:

<n>...</n>: 數字,用以區隔標題與列舉數字。

 

轉換工具

 

使用LamrimRader.Core處理論文的部分是TheoryUtil.parsePage(),如下範例程式所示,傳入要處理的頁數與監聽器二項,即可協助您生成論文文字,經過如下程式處理後,即可產生論文頁面。

TheoryUtil tu=new TheoryUtil(TheoryData.content);

TheoryParseListener listener = new TheoryParseListener() {
    @Override
    public void onSegmentFound(int line, int index, int length, String segText, boolean isBold, boolean isNum, boolean isSmall) {
        Log.d(getClass().getName(), "Found segment =" + segText);
        SpannableString str = new SpannableString(segText);
        if (isBold) {
            Log.d(getClass().getName(), "Set bold.");
            str.setSpan(new StyleSpan(android.graphics.Typeface.BOLD), 0, str.length(), Spannable.SPAN_INCLUSIVE_EXCLUSIVE);
        }
        if (isNum) {
            Log.d(getClass().getName(), "Set num.");
            str.setSpan(new ForegroundColorSpan(Color.rgb(0, 0, 255)), 0, str.length(), Spannable.SPAN_INCLUSIVE_EXCLUSIVE);
        }
        if (isSmall) {
            Log.d(getClass().getName(), "Set small.");
            str.setSpan(new RelativeSizeSpan(smallSize), 0, str.length(), Spannable.SPAN_INCLUSIVE_EXCLUSIVE);
        }
        pageView.append(str);
    }

    @Override
    public void onNewLineFound(int line, int index) {
        Log.d(getClass().getName(), "Found new line");
            pageView.append("\n");
        }

    @Override
    public void onFinishParse(ArrayList<Dot> dotList) {
        if(highlightMark != null && pageIndex == highlightMark.page)
            highlightText();
            pageView.drawDot(dotList);
        }
    };
}

tu.parsePage(num,listener);

 

請注意,處理廣論文字的部分與平台無關,但繪製標點符號在不同平台有不同的作法,端看您所開發的平台,標點符號列表會在onFinishParse()函示中交給您的程式,您必須自行實作繪製標點符號的功能。