/// <summary> /// 編排指定的列。此函式會將指定的列斷行。 /// </summary> /// <param name="brDoc">點字文件。</param> /// <param name="lineIndex">欲重新編排的列索引。</param> /// <returns>傳回編排後的列數。</returns> public int FormatLine(BrailleDocument brDoc, int lineIndex, ContextTagManager context) { BrailleLine brLine = brDoc.Lines[lineIndex]; RemoveContextTagsButTitle(brLine); // 清除情境標籤,除了標題標籤。 if (brLine.WordCount == 0) { brDoc.RemoveLine(lineIndex); return(0); } List <BrailleLine> newLines; newLines = BreakLine(brLine, brDoc.CellsPerLine, context); if (newLines == null) // 沒有斷行? { return(1); } // 移除原始的 line brLine.Clear(); brDoc.RemoveLine(lineIndex); // 加入斷行後的 lines brDoc.Lines.InsertRange(lineIndex, newLines); return(newLines.Count); }
private BrailleProcessor(ZhuyinReverseConverter zhuyinConverter) { m_Converters = new List <WordConverter>(); m_ContextTagConverter = new ContextTagConverter(); m_ChineseConverter = new ChineseWordConverter(zhuyinConverter); m_EnglishConverter = new EnglishWordConverter(); m_MathConverter = new MathConverter(); m_CoordConverter = new CoordinateConverter(); m_TableConverter = new TableConverter(); m_PhoneticConverter = new PhoneticConverter(); m_Tags = new Hashtable(); m_Tags.Add(TextTag.Name, "╴╴"); // key/value = 標籤/替換字元 m_Tags.Add(TextTag.BookName, "﹏﹏"); m_Tags.Add(TextTag.NumericItem, "#"); m_Tags.Add(TextTag.OrgPageNumber, s_DashesForOrgPageNumber); // 原書頁碼 m_Tags.Add(TextTag.Unit1End, new string('ˍ', 20)); // 大單元結束 m_Tags.Add(TextTag.Unit2End, new string('﹍', 20)); // 小單元結束 m_Tags.Add(TextTag.Unit3End, new string('﹋', 20)); // 小題結束 m_Tags.Add(TextTag.BrailleComment, "★"); // 點譯者註 m_ContextTagManager = new ContextTagManager(); m_InvalidChars = new List <CharPosition>(); m_ErrorMsg = new StringBuilder(); m_SuppressEvents = false; }
/// <summary> /// 編排點字文件。 /// </summary> public void FormatDocument(BrailleDocument doc) { ContextTagManager context = new ContextTagManager(); int index = 0; while (index < doc.Lines.Count) { ProcessIndentTags(doc, index, context); index += FormatLine(doc, index, context); } }
/// <summary> /// 處理縮排情境標籤:碰到縮排標籤時,將縮排次數更新至 ContextTagManager 物件,並移除此縮排標籤。 /// /// NOTE: 縮排標籤必須位於列首,一列可有多個連續縮排標籤,例如:<縮排><縮排>。 /// </summary> /// <param name="brDoc"></param> /// <param name="lineIndex"></param> /// <param name="context">情境物件。</param> /// <returns></returns> public void ProcessIndentTags(BrailleDocument brDoc, int lineIndex, ContextTagManager context) { BrailleLine brLine = brDoc.Lines[lineIndex]; int wordIdx = 0; ContextTag ctag; while (brLine.WordCount > 0) { ctag = context.Parse(brLine[0].Text, ContextTagNames.Indent); if (ctag != null) { brLine.RemoveAt(wordIdx); } else { break; } } }
/// <summary> /// 將一行點字串列斷成多行。 /// </summary> /// <param name="brLine">來源點字串列。</param> /// <param name="cellsPerLine">每行最大方數。</param> /// <param name="context">情境物件。</param> /// <returns>斷行之後的多行串列。若為 null 表示無需斷行(指定的點字串列未超過每行最大方數)。</returns> public List <BrailleLine> BreakLine(BrailleLine brLine, int cellsPerLine, ContextTagManager context) { if (context != null && context.IndentCount > 0) // 若目前位於縮排區塊中 { // 每列最大方數要扣掉縮排數量,並於事後補縮排的空方。 // NOTE: 必須在斷行之後才補縮排的空方! cellsPerLine -= context.IndentCount; } // 若指定的點字串列未超過每行最大方數,則無須斷行,傳回 null。 if (brLine.CellCount <= cellsPerLine) { // 補縮排的空方。 if (context != null && context.IndentCount > 0) // 若目前位於縮排區塊中 { this.Indent(brLine, context.IndentCount); } return(null); } List <BrailleLine> lines = new List <BrailleLine>(); BrailleLine newLine = null; int wordIndex = 0; int breakIndex = 0; bool needHyphen = false; bool isBroken = false; // 是否已經斷行了? int indents = 0; // 第一次斷行時,不會有系統自斷加上的縮排,因此初始為 0。 int maxCells = cellsPerLine;; // 計算折行之後的縮排格數。 indents = BrailleProcessor.CalcNewLineIndents(brLine); while (wordIndex < brLine.WordCount) { breakIndex = BrailleProcessor.CalcBreakPoint(brLine, maxCells, out needHyphen); newLine = brLine.Copy(wordIndex, breakIndex); // 複製到新行。 if (needHyphen) // 是否要附加連字號? { newLine.Words.Add(new BrailleWord("-", BrailleCellCode.Hyphen)); } newLine.TrimEnd(); // 去尾空白。 // 如果是折下來的新行,就自動補上需要縮排的格數。 if (isBroken) { for (int i = 0; i < indents; i++) { newLine.Insert(0, BrailleWord.NewBlank()); } } brLine.RemoveRange(0, breakIndex); // 從原始串列中刪除掉已經複製到新行的點字。 wordIndex = 0; lines.Add(newLine); // 防錯:檢驗每個斷行後的 line 的方數是否超過每列最大方數。 // 若超過,即表示之前的斷行處理有問題,須立即停止執行,否則錯誤會 // 直到在雙視編輯的 Grid 顯示時才出現 index out of range,不易抓錯! System.Diagnostics.Debug.Assert(newLine.CellCount <= cellsPerLine, "斷行錯誤! 超過每列最大方數!"); // 被折行之後的第一個字需要再根據規則調整。 EnglishBrailleRule.ApplyCapitalRule(brLine); // 套用大寫規則。 EnglishBrailleRule.ApplyDigitRule(brLine); // 套用數字規則。 isBroken = true; // 已經至少折了一行 maxCells = cellsPerLine - indents; // 下一行開始就要自動縮排,共縮 indents 格。 } // 補縮排的空方。 if (context != null && context.IndentCount > 0) // 若目前位於縮排區塊中 { indents = context.IndentCount; foreach (BrailleLine aLine in lines) { this.Indent(aLine, indents); } } return(lines); }