【问题标题】:Itext missing line break on chunkItext在块上缺少换行符
【发布时间】:2016-01-13 11:26:36
【问题描述】:

我正在使用 Itext 生成 pdf,我需要执行 Chunk.keepOnSameLine 之类的操作。

我正在构建一个短语,它可以包含由多个块组成的多行,当行结束时,我希望块不被破坏。

块是名称和日期。例如:“约翰·史密斯 (2016-01-13 11:13)”

代码是这样的

    Phrase p = new Phrase();
    Chunk c1 = new Chunk("FirstName LastName (2016-01-13 11:13)");
    p.Add(c1);
    Chunk c2 = new Chunk("FirstName LastName (2016-01-13 11:13)")
    p.Add(c2);
    Chunk c3 = new Chunk("FirstName LastName (2016-01-13 11:13)")
    p.Add(c3);
    Chunk c4 = new Chunk("FirstName LastName (2016-01-13 11:13)")
    p.Add(c4);
    Chunk c5 = new Chunk("FirstName LastName (2016-01-13 11:13)")
    p.Add(c5);
    Chunk c6 = new Chunk("FirstName LastName (2016-01-13 11:13)")
    p.Add(c6);
    Chunk c7 = new Chunk("FirstName LastName (2016-01-13 11:13)")
    p.Add(c7);

(代码是动态的,所以我不知道会有多少块存在。

结果短语显示为like

然后将生成的短语添加到 PdfPCell

【问题讨论】:

  • 我看到 Itext 在从 PDF 导入文本时倾向于插入软连字符。我想知道相反的情况是否也是如此!您可以尝试在每个块的末尾添加一个软连字符,看看它是否会改变中断行为。
  • 是的,问题是连字符是一个中断字符...
  • 不应呈现软连字符,它的唯一目的是提示在哪里中断。希望它应该在选择任意中断点之前中断软连字符。
  • 但我的意思是中断应该在名字之前,而不是在块的中间
  • 你可以尝试在块的末尾添加一个软连字符:)

标签: itext


【解决方案1】:

您可以通过实现 ISplitCharacter 并用您自己的替换默认值(连字符和空格)来修改 iText 拆分行的方式:

public class CustomSplitCharacter : ISplitCharacter
{
    public bool IsSplitCharacter(
        int start, int current, int end, char[] cc, PdfChunk[] ck)
    {
        char c = ck == null
            ? cc[current]
            : (char)ck[Math.Min(current, ck.Length - 1)]
                .GetUnicodeEquivalent(cc[current])
        ;
        return (c == ')');
    }
}

然后在Chunk上拨打SetSplitCharacter()

string chunkText = "FirstName LastName (2016-01-13 11:13)";
Random random = new Random();
var font = new Font(Font.FontFamily.HELVETICA, 10, Font.BOLD); 
using (Document document = new Document())
{
    PdfWriter.GetInstance(document, stream);
    document.Open();
    Phrase phrase = new Phrase();
    for (var i = 0; i < 1000; ++i)
    {
        var asterisk = new String('*', random.Next(1, 20));
        Chunk chunk = new Chunk(
            string.Format("[{0}] {1}", asterisk, chunkText), 
            font
        );
        chunk.SetSplitCharacter(new CustomSplitCharacter());
        phrase.Add(chunk);
    }

    document.Add(phrase);
}

这假设您的Chunk) 结尾,就像您的示例代码一样,或者您可以控制Chunk 的最后一个文本字符。

不依赖于特定字体。 :)

【讨论】:

    【解决方案2】:

    使用 Unicode U+00A0,即 non-breaking space。您还需要使用U+2011,即non-breaking hyphen。但是,从技术上讲,不间断连字符与常规连字符是不同的字符,因此您也需要支持它的字体。

    var testString = "FirstName LastName (2016-01-13 11:13)";
    var nbsp = "\u00a0";
    var nbhy = "\u2011";
    
    //With a normal space
    var p1 = new Phrase();
    for (var i = 0; i < 100; i++) {
        p1.Add(new Chunk(testString + " "));
    }
    doc.Add(p1);
    
    
    //Create a font that supports our "hard hyphen"
    var bf = BaseFont.CreateFont(fontFile, BaseFont.IDENTITY_H, BaseFont.EMBEDDED);
    var f = new iTextSharp.text.Font(bf, 12);
    testString = testString.Replace(" ", nbsp).Replace("-", nbhy);
    
    //With a non-breaking space
    var p2 = new Phrase();
    for (var i = 0; i < 100; i++) {
        p2.Add(new Chunk(testString + " ", f));
    }
    doc.Add(p2);
    

    【讨论】:

    • 我已经不明白不破连字符的问题了,但是我把它放了也没用。不,我理解是因为字体问题。不,我有一个问题,我的所有字体都被声明为font_bigBold = new Font(Font.FontFamily.HELVETICA, 18, Font.BOLD); CreateFont 上使用的fontFile 是什么?
    • PDF 规范声明了所有符合者(如 iText 和 Adob​​e Reader)都必须“意识到”的 4 种文本字体和 1 种符号字体(计算变体时总共 14 种),FontFamily.HELVETICA 就是其中之一.这些核心文本字体支持 7 位 ASCII 标准,但在 8 位部分会变灰。从本质上讲,如果您不指定自己的字体,您将依赖 90 年代早期的字体(或者 80 年代,如果它们来自 PostScript)。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2017-04-15
    • 1970-01-01
    • 1970-01-01
    • 2022-07-25
    • 2016-10-01
    相关资源
    最近更新 更多