Example #1
0
 public void GetNext(out char c, out bool inHL)
 {
     if (runPos >= runTxt.Length)
     {
         ++runIX;
         runPos = 0;
         if (runIX < txt.RunCount)
         {
             runTxt = txt.GetRunAt(runIX).GetPlainText();
         }
         else
         {
             runTxt = null;
         }
     }
     if (runTxt == null)
     {
         c    = (char)0;
         inHL = false;
         return;
     }
     c = runTxt[runPos];
     if (hl == null || hl.RunIx != runIX)
     {
         inHL = false;
     }
     else
     {
         inHL = runPos >= hl.HiliteStart && runPos < hl.HiliteStart + hl.HiliteLength;
     }
     ++runPos;
 }
Example #2
0
        /// <summary>
        /// Converts a hybrid text to CEDICT-formatted plain text (marking up hanzi+pinyin sections).
        /// </summary>
        public static string HybridToCedict(HybridText ht)
        {
            StringBuilder sb    = new StringBuilder();
            bool          first = true;

            for (int i = 0; i != ht.RunCount; ++i)
            {
                TextRun tr = ht.GetRunAt(i);
                if (tr is TextRunLatin)
                {
                    string strRun = tr.GetPlainText();
                    if (!first && strRun != string.Empty && !char.IsPunctuation(strRun[0]))
                    {
                        sb.Append(' ');
                    }
                    sb.Append(strRun);
                }
                else
                {
                    if (!first)
                    {
                        sb.Append(' ');
                    }
                    TextRunZho trz = tr as TextRunZho;
                    if (!string.IsNullOrEmpty(trz.Simp))
                    {
                        sb.Append(trz.Simp);
                    }
                    if (trz.Trad != trz.Simp && !string.IsNullOrEmpty(trz.Trad))
                    {
                        sb.Append('|');
                        sb.Append(trz.Trad);
                    }
                    if (trz.Pinyin != null)
                    {
                        sb.Append('[');
                        sb.Append(GetPinyinCedict(trz.Pinyin));
                        sb.Append(']');
                    }
                }
                first = false;
            }
            return(sb.ToString());
        }
Example #3
0
 /// <summary>
 /// Returns true if display font covers all Hanzi in hybrid text; false otherwise.
 /// </summary>
 private bool areHanziCovered(HybridText ht)
 {
     if (ht.IsEmpty)
     {
         return(true);
     }
     for (int i = 0; i != ht.RunCount; ++i)
     {
         TextRun    tr    = ht.GetRunAt(i);
         TextRunZho trJoe = tr as TextRunZho;
         if (trJoe == null)
         {
             continue;
         }
         if (trJoe.Simp == null)
         {
             continue;
         }
         foreach (char c in trJoe.Simp)
         {
             if (!cvr.GetCoverage(c).HasFlag(FontCoverageFlags.Simp))
             {
                 return(false);
             }
         }
         if (trJoe.Trad == null)
         {
             continue;
         }
         foreach (char c in trJoe.Trad)
         {
             if (!cvr.GetCoverage(c).HasFlag(FontCoverageFlags.Trad))
             {
                 return(false);
             }
         }
     }
     return(true);
 }
        /// <summary>
        /// <para>Produces unmeasured display blocks from a single hybrid text. Marks highlights, if any.</para>
        /// <para>Does not fill in blocks' size, but fills in everything else.</para>
        /// </summary>
        /// <param name="htxt">Hybrid text to break down into blocks and measure.</param>
        /// <param name="isMeta">True if this is a domain or note (displayed in italics).</param>
        /// <param name="hl">Highlight to show in hybrid text, or null.</param>
        /// <param name="blocks">List of blocks to append to.</param>
        /// <param name="links">List to gather links (appending to list).</param>
        private void makeBlocks(HybridText htxt, bool isMeta, CedictTargetHighlight hl,
            List<Block> blocks, List<LinkArea> links)
        {
            byte fntIdxLatin = isMeta ? fntMetaLatin : fntSenseLatin;
            byte fntIdxZhoSimp = isMeta ? fntMetaHanziSimp : fntSenseHanziSimp;
            byte fntIdxZhoTrad = isMeta ? fntMetaHanziTrad : fntSenseHanziTrad;
            // Go run by run
            for (int runIX = 0; runIX != htxt.RunCount; ++runIX)
            {
                TextRun run = htxt.GetRunAt(runIX);
                // Latin run: split by spaces first
                if (run is TextRunLatin)
                {
                    string[] bySpaces = run.GetPlainText().Split(new char[] { ' ' });
                    // Each word: also by dash
                    int latnPos = 0;
                    foreach (string str in bySpaces)
                    {
                        string[] byDashes = splitByDash(str);
                        // Add block for each
                        int ofsPos = 0;
                        foreach (string blockStr in byDashes)
                        {
                            Block tb = new Block
                            {
                                TextPos = textPool.PoolString(blockStr),
                                FontIdx = fntIdxLatin,
                                SpaceAfter = false, // will set this true for last block in "byDashes"
                            };
                            // Does block's text intersect with highlight?
                            if (hl != null && hl.RunIx == runIX)
                            {
                                int blockStart = latnPos + ofsPos;
                                int blockEnd = blockStart + blockStr.Length;
                                if (blockStart >= hl.HiliteStart && blockStart < hl.HiliteStart + hl.HiliteLength)
                                    tb.Hilite = true;
                                else if (blockEnd > hl.HiliteStart && blockEnd <= hl.HiliteStart + hl.HiliteLength)
                                    tb.Hilite = true;
                                else if (blockStart < hl.HiliteStart && blockEnd >= hl.HiliteStart + hl.HiliteLength)
                                    tb.Hilite = true;
                            }
                            blocks.Add(tb);
                            // Keep track of position for highlight
                            ofsPos += blockStr.Length;
                        }
                        // Make sure last one is followed by space
                        Block xb = blocks[blocks.Count - 1];
                        xb.SpaceAfter = true;
                        blocks[blocks.Count - 1] = xb;
                        // Keep track of position in text - for highlights
                        latnPos += str.Length + 1;
                    }
                }
                // Chinese: depends on T/S/Both display mode, and on available info
                else
                {
                    TextRunZho zhoRun = run as TextRunZho;
                    // Chinese range is made up of:
                    // Simplified (empty string if only traditional requested)
                    // Separator (if both simplified and traditional are requested)
                    // Traditional (empty string if only simplified requested)
                    // Pinyin with accents as tone marks, in brackets (if present)
                    string strSimp = string.Empty;
                    if (analyzedScript != SearchScript.Traditional && zhoRun.Simp != null) strSimp = zhoRun.Simp;
                    string strTrad = string.Empty;
                    if (analyzedScript != SearchScript.Simplified && zhoRun.Trad != null) strTrad = zhoRun.Trad;
                    string strPy = string.Empty;
                    // Convert pinyin to display format (tone marks as diacritics; r5 glued)
                    if (zhoRun.Pinyin != null) strPy = "[" + zhoRun.GetPinyinInOne(true) + "]";

                    // Create link area, with query string
                    string strPyNumbers = string.Empty; // Pinyin with numbers as tone marks
                    if (zhoRun.Pinyin != null) strPyNumbers = zhoRun.GetPinyinRaw();
                    LinkArea linkArea = new LinkArea(strSimp, strTrad, strPyNumbers, analyzedScript);

                    // Block for simplified, if present
                    if (strSimp != string.Empty)
                    {
                        Block tb = new Block
                        {
                            TextPos = textPool.PoolString(strSimp),
                            FontIdx = fntIdxZhoSimp,
                            SpaceAfter = true,
                        };
                        blocks.Add(tb);
                        linkArea.BlockIds.Add(blocks.Count - 1);
                    }
                    // Separator if both simplified and traditional are there
                    // AND they are different...
                    if (strSimp != string.Empty && strTrad != string.Empty && strSimp != strTrad)
                    {
                        Block xb = blocks[blocks.Count - 1];
                        xb.StickRight = true;
                        blocks[blocks.Count - 1] = xb;
                        Block tb = new Block
                        {
                            TextPos = textPool.PoolString("•"),
                            FontIdx = fntIdxLatin,
                            SpaceAfter = true,
                        };
                        blocks.Add(tb);
                        linkArea.BlockIds.Add(blocks.Count - 1);
                    }
                    // Traditional, if present
                    if (strTrad != string.Empty && strTrad != strSimp)
                    {
                        Block tb = new Block
                        {
                            TextPos = textPool.PoolString(strTrad),
                            FontIdx = fntIdxZhoTrad,
                            SpaceAfter = true,
                        };
                        blocks.Add(tb);
                        linkArea.BlockIds.Add(blocks.Count - 1);
                    }
                    // Pinyin, if present
                    if (strPy != string.Empty)
                    {
                        // Split by spaces
                        string[] pyParts = strPy.Split(new char[] { ' ' });
                        foreach (string pyPart in pyParts)
                        {
                            Block tb = new Block
                            {
                                TextPos = textPool.PoolString(pyPart),
                                FontIdx = fntIdxLatin,
                                SpaceAfter = true,
                            };
                            blocks.Add(tb);
                            linkArea.BlockIds.Add(blocks.Count - 1);
                        }
                    }
                    // Last part will have requested a space after.
                    // Look ahead and if next text run is Latin and starts with punctuation, make it stick
                    TextRunLatin nextLatinRun = null;
                    if (runIX + 1 < htxt.RunCount) nextLatinRun = htxt.GetRunAt(runIX + 1) as TextRunLatin;
                    if (nextLatinRun != null && char.IsPunctuation(nextLatinRun.GetPlainText()[0]))
                    {
                        Block xb = blocks[blocks.Count - 1];
                        xb.SpaceAfter = false;
                        blocks[blocks.Count - 1] = xb;
                    }
                    // Collect link area
                    links.Add(linkArea);
                }
            }
        }
Example #5
0
        /// <summary>
        /// Converts a hybrid text to HTML (marking up hanzi+pinyin sections).
        /// </summary>
        public static string HybridToHtml(HybridText ht, SearchScript script)
        {
            StringBuilder sb = new StringBuilder();

            bool first = true;

            for (int i = 0; i != ht.RunCount; ++i)
            {
                TextRun tr = ht.GetRunAt(i);
                if (tr is TextRunLatin)
                {
                    string strRun = tr.GetPlainText();
                    if (!first && strRun != string.Empty && !char.IsPunctuation(strRun[0]))
                    {
                        sb.Append(' ');
                    }
                    sb.Append(strRun);
                }
                else
                {
                    if (!first)
                    {
                        sb.Append(' ');
                    }
                    TextRunZho trz = tr as TextRunZho;

                    string hanzi1 = (script == SearchScript.Traditional) ? trz.Trad : trz.Simp;
                    if (string.IsNullOrEmpty(hanzi1))
                    {
                        hanzi1 = null;
                    }
                    string hanzi2 = null;
                    if (hanzi1 != null && script == SearchScript.Both && !string.IsNullOrEmpty(trz.Trad))
                    {
                        hanzi2 = trz.Trad;
                    }
                    if (hanzi1 != null)
                    {
                        hanzi1 = escape(hanzi1);
                    }
                    if (hanzi2 != null)
                    {
                        hanzi2 = escape(hanzi2);
                    }

                    if (hanzi1 != null || hanzi2 != null)
                    {
                        sb.Append(templateSenseHanziOpen);
                    }
                    if (hanzi1 != null)
                    {
                        sb.Append(hanzi1);
                    }
                    if (hanzi2 != null)
                    {
                        sb.Append(' ');
                        sb.Append(templateBullet);
                        sb.Append(' ');
                        sb.Append(hanzi2);
                    }
                    if (hanzi1 != null || hanzi2 != null)
                    {
                        sb.Append(templateSenseHanziClose);
                    }

                    if (trz.Pinyin != null)
                    {
                        if (hanzi1 != null)
                        {
                            sb.Append(' ');
                        }
                        sb.Append('[');
                        sb.Append(escape(trz.GetPinyinInOne(true)));
                        sb.Append(']');
                    }
                }
                first = false;
            }
            return(sb.ToString());
        }
Example #6
0
        /// <summary>
        /// Converts a hybrid text to HTML (marking up hanzi+pinyin sections).
        /// </summary>
        public static string HybridToHtml(HybridText ht, SearchScript script)
        {
            StringBuilder sb = new StringBuilder();

            bool first = true;
            for (int i = 0; i != ht.RunCount; ++i)
            {
                TextRun tr = ht.GetRunAt(i);
                if (tr is TextRunLatin)
                {
                    string strRun = tr.GetPlainText();
                    if (!first && strRun != string.Empty && !char.IsPunctuation(strRun[0])) sb.Append(' ');
                    sb.Append(strRun);
                }
                else
                {
                    if (!first) sb.Append(' ');
                    TextRunZho trz = tr as TextRunZho;

                    string hanzi1 = (script == SearchScript.Traditional) ? trz.Trad : trz.Simp;
                    if (string.IsNullOrEmpty(hanzi1)) hanzi1 = null;
                    string hanzi2 = null;
                    if (hanzi1 != null && script == SearchScript.Both && !string.IsNullOrEmpty(trz.Trad))
                        hanzi2 = trz.Trad;
                    if (hanzi1 != null) hanzi1 = escape(hanzi1);
                    if (hanzi2 != null) hanzi2 = escape(hanzi2);

                    if (hanzi1 != null || hanzi2 != null) sb.Append(templateSenseHanziOpen);
                    if (hanzi1 != null) sb.Append(hanzi1);
                    if (hanzi2 != null)
                    {
                        sb.Append(' ');
                        sb.Append(templateBullet);
                        sb.Append(' ');
                        sb.Append(hanzi2);
                    }
                    if (hanzi1 != null || hanzi2 != null) sb.Append(templateSenseHanziClose);

                    if (trz.Pinyin != null)
                    {
                        if (hanzi1 != null) sb.Append(' ');
                        sb.Append('[');
                        sb.Append(escape(trz.GetPinyinInOne(true)));
                        sb.Append(']');
                    }
                }
                first = false;
            }
            return sb.ToString();
        }
Example #7
0
 /// <summary>
 /// Converts a hybrid text to CEDICT-formatted plain text (marking up hanzi+pinyin sections).
 /// </summary>
 public static string HybridToCedict(HybridText ht)
 {
     StringBuilder sb = new StringBuilder();
     bool first = true;
     for (int i = 0; i != ht.RunCount; ++i)
     {
         TextRun tr = ht.GetRunAt(i);
         if (tr is TextRunLatin)
         {
             string strRun = tr.GetPlainText();
             if (!first && strRun != string.Empty && !char.IsPunctuation(strRun[0])) sb.Append(' ');
             sb.Append(strRun);
         }
         else
         {
             if (!first) sb.Append(' ');
             TextRunZho trz = tr as TextRunZho;
             if (!string.IsNullOrEmpty(trz.Simp)) sb.Append(trz.Simp);
             if (trz.Trad != trz.Simp && !string.IsNullOrEmpty(trz.Trad))
             {
                 sb.Append('|');
                 sb.Append(trz.Trad);
             }
             if (trz.Pinyin != null)
             {
                 sb.Append('[');
                 sb.Append(GetPinyinCedict(trz.Pinyin));
                 sb.Append(']');
             }
         }
         first = false;
     }
     return sb.ToString();
 }
Example #8
0
 /// <summary>
 /// Returns true if display font covers all Hanzi in hybrid text; false otherwise.
 /// </summary>
 private bool areHanziCovered(HybridText ht)
 {
     if (ht.IsEmpty) return true;
     for (int i = 0; i != ht.RunCount; ++i)
     {
         TextRun tr = ht.GetRunAt(i);
         TextRunZho trJoe = tr as TextRunZho;
         if (trJoe == null) continue;
         if (trJoe.Simp == null) continue;
         foreach (char c in trJoe.Simp)
             if (!cvr.GetCoverage(c).HasFlag(FontCoverageFlags.Simp))
                 return false;
         if (trJoe.Trad == null) continue;
         foreach (char c in trJoe.Trad)
             if (!cvr.GetCoverage(c).HasFlag(FontCoverageFlags.Trad))
                 return false;
     }
     return true;
 }
Example #9
0
 public HybridTextConsumer(HybridText txt, CedictTargetHighlight hl)
 {
     this.txt = txt;
     this.hl  = hl;
     runTxt   = txt.GetRunAt(0).GetPlainText();
 }
        /// <summary>
        /// <para>Produces unmeasured display blocks from a single hybrid text. Marks highlights, if any.</para>
        /// <para>Does not fill in blocks' size, but fills in everything else.</para>
        /// </summary>
        /// <param name="htxt">Hybrid text to break down into blocks and measure.</param>
        /// <param name="isMeta">True if this is a domain or note (displayed in italics).</param>
        /// <param name="hl">Highlight to show in hybrid text, or null.</param>
        /// <param name="blocks">List of blocks to append to.</param>
        /// <param name="links">List to gather links (appending to list).</param>
        private void makeBlocks(HybridText htxt, bool isMeta, CedictTargetHighlight hl,
                                List <Block> blocks, List <LinkArea> links)
        {
            byte fntIdxLatin   = isMeta ? fntMetaLatin : fntSenseLatin;
            byte fntIdxZhoSimp = isMeta ? fntMetaHanziSimp : fntSenseHanziSimp;
            byte fntIdxZhoTrad = isMeta ? fntMetaHanziTrad : fntSenseHanziTrad;

            // Go run by run
            for (int runIX = 0; runIX != htxt.RunCount; ++runIX)
            {
                TextRun run = htxt.GetRunAt(runIX);
                // Latin run: split by spaces first
                if (run is TextRunLatin)
                {
                    string[] bySpaces = run.GetPlainText().Split(new char[] { ' ' });
                    // Each word: also by dash
                    int latnPos = 0;
                    foreach (string str in bySpaces)
                    {
                        string[] byDashes = splitByDash(str);
                        // Add block for each
                        int ofsPos = 0;
                        foreach (string blockStr in byDashes)
                        {
                            Block tb = new Block
                            {
                                TextPos    = textPool.PoolString(blockStr),
                                FontIdx    = fntIdxLatin,
                                SpaceAfter = false, // will set this true for last block in "byDashes"
                            };
                            // Does block's text intersect with highlight?
                            if (hl != null && hl.RunIx == runIX)
                            {
                                int blockStart = latnPos + ofsPos;
                                int blockEnd   = blockStart + blockStr.Length;
                                if (blockStart >= hl.HiliteStart && blockStart < hl.HiliteStart + hl.HiliteLength)
                                {
                                    tb.Hilite = true;
                                }
                                else if (blockEnd > hl.HiliteStart && blockEnd <= hl.HiliteStart + hl.HiliteLength)
                                {
                                    tb.Hilite = true;
                                }
                                else if (blockStart < hl.HiliteStart && blockEnd >= hl.HiliteStart + hl.HiliteLength)
                                {
                                    tb.Hilite = true;
                                }
                            }
                            blocks.Add(tb);
                            // Keep track of position for highlight
                            ofsPos += blockStr.Length;
                        }
                        // Make sure last one is followed by space
                        Block xb = blocks[blocks.Count - 1];
                        xb.SpaceAfter            = true;
                        blocks[blocks.Count - 1] = xb;
                        // Keep track of position in text - for highlights
                        latnPos += str.Length + 1;
                    }
                }
                // Chinese: depends on T/S/Both display mode, and on available info
                else
                {
                    TextRunZho zhoRun = run as TextRunZho;
                    // Chinese range is made up of:
                    // Simplified (empty string if only traditional requested)
                    // Separator (if both simplified and traditional are requested)
                    // Traditional (empty string if only simplified requested)
                    // Pinyin with accents as tone marks, in brackets (if present)
                    string strSimp = string.Empty;
                    if (analyzedScript != SearchScript.Traditional && zhoRun.Simp != null)
                    {
                        strSimp = zhoRun.Simp;
                    }
                    string strTrad = string.Empty;
                    if (analyzedScript != SearchScript.Simplified && zhoRun.Trad != null)
                    {
                        strTrad = zhoRun.Trad;
                    }
                    string strPy = string.Empty;
                    // Convert pinyin to display format (tone marks as diacritics; r5 glued)
                    if (zhoRun.Pinyin != null)
                    {
                        strPy = "[" + zhoRun.GetPinyinInOne(true) + "]";
                    }

                    // Create link area, with query string
                    string strPyNumbers = string.Empty; // Pinyin with numbers as tone marks
                    if (zhoRun.Pinyin != null)
                    {
                        strPyNumbers = zhoRun.GetPinyinRaw();
                    }
                    LinkArea linkArea = new LinkArea(strSimp, strTrad, strPyNumbers, analyzedScript);

                    // Block for simplified, if present
                    if (strSimp != string.Empty)
                    {
                        Block tb = new Block
                        {
                            TextPos    = textPool.PoolString(strSimp),
                            FontIdx    = fntIdxZhoSimp,
                            SpaceAfter = true,
                        };
                        blocks.Add(tb);
                        linkArea.BlockIds.Add(blocks.Count - 1);
                    }
                    // Separator if both simplified and traditional are there
                    // AND they are different...
                    if (strSimp != string.Empty && strTrad != string.Empty && strSimp != strTrad)
                    {
                        Block xb = blocks[blocks.Count - 1];
                        xb.StickRight            = true;
                        blocks[blocks.Count - 1] = xb;
                        Block tb = new Block
                        {
                            TextPos    = textPool.PoolString("•"),
                            FontIdx    = fntIdxLatin,
                            SpaceAfter = true,
                        };
                        blocks.Add(tb);
                        linkArea.BlockIds.Add(blocks.Count - 1);
                    }
                    // Traditional, if present
                    if (strTrad != string.Empty && strTrad != strSimp)
                    {
                        Block tb = new Block
                        {
                            TextPos    = textPool.PoolString(strTrad),
                            FontIdx    = fntIdxZhoTrad,
                            SpaceAfter = true,
                        };
                        blocks.Add(tb);
                        linkArea.BlockIds.Add(blocks.Count - 1);
                    }
                    // Pinyin, if present
                    if (strPy != string.Empty)
                    {
                        // Split by spaces
                        string[] pyParts = strPy.Split(new char[] { ' ' });
                        foreach (string pyPart in pyParts)
                        {
                            Block tb = new Block
                            {
                                TextPos    = textPool.PoolString(pyPart),
                                FontIdx    = fntIdxLatin,
                                SpaceAfter = true,
                            };
                            blocks.Add(tb);
                            linkArea.BlockIds.Add(blocks.Count - 1);
                        }
                    }
                    // Last part will have requested a space after.
                    // Look ahead and if next text run is Latin and starts with punctuation, make it stick
                    TextRunLatin nextLatinRun = null;
                    if (runIX + 1 < htxt.RunCount)
                    {
                        nextLatinRun = htxt.GetRunAt(runIX + 1) as TextRunLatin;
                    }
                    if (nextLatinRun != null && char.IsPunctuation(nextLatinRun.GetPlainText()[0]))
                    {
                        Block xb = blocks[blocks.Count - 1];
                        xb.SpaceAfter            = false;
                        blocks[blocks.Count - 1] = xb;
                    }
                    // Collect link area
                    links.Add(linkArea);
                }
            }
        }