.net - 如何在 iText7/iText7.pdfhtml 的行首修复 CJK 标点符号
问题描述
我在使用 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);
}
我的源代码在这里:源代码
我的问题如下:
非常感谢您提前提供的帮助!
解决方案
我想问题出在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);
}
另请注意,您的实现效率不是很高,您应该用 HashSets 替换 char 数组以加快查找速度,该Contains
查找现在与您的数组大小成线性关系。此外,您应该在类中创建一次作为字段并重用它,而不是DefaultSplitCharacters
每次都在 中创建实例。IsSplitCharacter
CJKSplitCharacters
推荐阅读
- python - 无法安装 Visual Studio Code 的 Python 扩展
- sql-server - 如果 SQL Server 中 2 列的值相同,如何从表中只获取一个数据?
- javascript - 使用 HTML 显示来自 Fetch 的响应?
- ag-grid - 浮动过滤器的 AG-Grid 变化值
- r - 添加索引?到已经存在的列,因为它们位于错误的列中
- sql-server - 当涉及 SUM 的多个 case 语句时,如何组合以下 2 个 sql 查询
- java - 我可以在自定义注释上使用任何注释吗
- python - 如何在 Python 中并排打印两个 for 循环的结果?
- python - def() 中的错误返回输出
- python - 用于 sftp AND 命令执行的服务器实现(使用 Paramiko)