【问题标题】:How to fix CJK punctuation at the beginning of line in iText7/iText7.pdfhtml如何在 iText7/iText7.pdfhtml 的行首修复 CJK 标点符号
【发布时间】:2019-01-08 14:44:36
【问题描述】:

我在使用 iText7/iText7.pdfhtml 将 HTML 字符串转换为 PDF 文件时遇到了这个问题。我发现了一些类似的问题,例如:

但是这些问题的解决方案是针对 iText5 的,我在我的应用程序中尝试了这些解决方案,但最终失败了。我的代码是这样的:

IList<IElement> elements = HtmlConverter.ConvertToElements(pdfHtmlString, properties);
Document document = new Document(pdfDoc);
CJKSplitCharacters splitCharacters = new CJKSplitCharacters();
document.SetFontProvider(fp);
document.SetSplitCharacters(splitCharacters);
document.SetProperty(Property.SPLIT_CHARACTERS, splitCharacters);
foreach (IElement e in elements)
{
     try
     {
          document.Add((AreaBreak)e);
     }
     catch
     {
          document.Add((IBlockElement)e);
     }
}

CJKSplitCharacters 的代码:

public class CJKSplitCharacters : ISplitCharacters
{
    // line of text cannot start or end with this character
    static char u2060 = '\u2060';   //       - ZERO WIDTH NO BREAK SPACE

    // a line of text cannot start with any following characters in NOT_BEGIN_CHARACTERS[]
    static char[] NOT_BEGIN_CHARACTERS = new char[]{u30fb, u2022, uff65, u300d, uff09, u0021, u0025, u0029, u002c,
      u002e, u003f, u005d, u007d, uff61, uff63, uff64, uff67, uff68, uff69, uff6a, uff6b, uff6c, uff6d, uff6e,
      uff6f, uff70, uff9e, uff9f, u3001, u3002, uff0c, uff0e, uff1a, uff1b, uff1f, uff01, u309b, u309c, u30fd,
      u30fe, u309d, u309e, u3005, u30fc, u2019, u201d, u3015, uff3d, uff5d, u3009, u300b, u300f, u3011, u00b0,
      u2032, u2033, u2103, u00a2, uff05, u2030, u3041, u3043, u3045, u3047, u3049, u3063, u3083, u3085, u3087,
      u308e, u30a1, u30a3, u30a5, u30a7, u30a9, u30c3, u30e3, u30e5, u30e7, u30ee, u30f5, u30f6, u2060};

    // a line of text cannot end with any following characters in NOT_ENDING_CHARACTERS[]
    static char[] NOT_ENDING_CHARACTERS = new char[]{u0024, u0028, u005b, u007b, u00a3, u00a5, u201c, u2018, u3008,
      u300a, u300c, u300e, u3010, u3014, uff62, uff08, uff3b, uff5b, uffe5, uff04, u2060};

    /// <summary>
    /// 
    /// </summary>
    /// <param name="text"></param>
    /// <param name="glyphPos"></param>
    /// <returns></returns>
    public bool IsSplitCharacter(GlyphLine text, int glyphPos)
    {
        if (!text.Get(glyphPos).HasValidUnicode())
        {
            return false;
        }
        int charCode = text.Get(glyphPos).GetUnicode();

        if (NOT_BEGIN_CHARACTERS.Contains((char)charCode))
        {
            return false;
        }
        return new DefaultSplitCharacters().IsSplitCharacter(text, glyphPos);
    }

我的源代码在这里:Source Code

我的问题如下:

非常感谢您提前提供的帮助!

【问题讨论】:

  • 感谢您在 GitHub 上发布的可重现项目。未来提示:发布最小的可重现样本,包括您尝试转换的字符串/HTML。例如。对我来说,我不可能手动输入这些字形。

标签: .net itext7


【解决方案1】:

我猜问题出在IsSplitCharacter 方法的实现上。您没有使用NOT_ENDING_CHARACTERS,仅使用NOT_BEGIN_CHARACTERS

虽然由于缺少源字符串数据(这意味着我尚未测试我的方法),我无法重现您的示例,但我认为您应该实现该方法的方式如下:

public bool IsSplitCharacter(GlyphLine text, int glyphPos)
{
    if (!text.Get(glyphPos).HasValidUnicode())
    {
        return false;
    }
    int charCode = text.Get(glyphPos).GetUnicode();

    if (NOT_ENDING_CHARACTERS.Contains((char)charCode))
    {
        return false;
    }

    // Look ahead for the next non-whitespace character and check it not to be in NOT_BEGIN_CHARACTERS list
    for (int i = 1; glyphPos + i < text.end; i++)
    {
        if (!text.Get(glyphPos + i).HasValidUnicode())
        {
            break;
        }
        if (!TextUtil.isSpaceOrWhitespace(text.Get(glyphPos + i)))
        {
            if (NOT_BEGIN_CHARACTERS.Contains(text.Get(glyphPos + i).GetUnicode()))
            {
                return false;
            }
            break;
        }
    }

    return new DefaultSplitCharacters().IsSplitCharacter(text, glyphPos);
}

还请注意,您的实现效率不高,您应该用 HashSet 替换 char 数组以加快 Contains 查找速度,该查找现在与您的数组大小成线性关系。此外,不要每次在 IsSplitCharacter 中创建 DefaultSplitCharacters 实例,您应该在 CJKSplitCharacters 类中将其创建为一个字段并重用它。

【讨论】:

  • 嗨@AlexeySubach,感谢您在这里的回答。我在这里尝试过您的解决方案,发现效果很好。似乎缺少NOT_ENDING_CHARACTERS 会导致此问题。并且在这里也感谢您的提示,我将来会注意这些提示。最美好的祝愿!
猜你喜欢
  • 2021-08-29
  • 1970-01-01
  • 1970-01-01
  • 2020-01-29
  • 1970-01-01
  • 2020-10-11
  • 1970-01-01
  • 1970-01-01
  • 2022-11-25
相关资源
最近更新 更多