jsPDF文本对齐

15

我正在尝试对jsPDF库进行一些更改,以便能够调整文本对齐。

我遇到了一些困难,无法找到Tw的正确值(单词间距)。

jspdf.js (L:1413)中,我添加了以下代码:

if (align) {
    ...                
    else if (align === 'justify') {
       left = x;
    }
    else {
        throw new Error('Unrecognized alignment option, use "center" or "right".');
    }
    prevX = x;
    text = '(' + da[0];

    let pdfPageWidth = this.internal.pageSize.width;
    let wordSpacing;
    if( align === 'justify' ) {
        let fontSize = this.internal.getFontSize();
        let nWords = da[0].trim().split(/\s+/).length;
        let textWidth = this.getStringUnitWidth(da[0].replace(/\s+/g, '')) / this.internal.scaleFactor;
        wordSpacing = (Math.max(0, (pdfPageWidth - textWidth) / Math.max(1, nWords - 1));
        wordSpacing += ' Tw\n';
        text = wordSpacing + text;
    }
    ...
}

这个想法是通过执行(pageWidth - textWidth) / numberOfWords -1来提取空格宽度。我无法获得正确的单词间距。

BT
/F1 16 Tf
18.4 TL
0 g
28.35 756.85 Td
19.00357142857142 Tw
(And a little bit it adélkfjalké.) Tj
ET

有编码问题吗?

谢谢你的帮助。


1
使用哪种字体编码?根据规范:“在使用简单字体或定义代码32为单字节代码的复合字体时,单字节字符代码32的每个出现都应用单词间距。它不适用于多字节代码中字节值32的出现。”如果您有一种编码方式,该编码方式不将空格字形编码为单个字节0x20,则无法按预期应用单词间距。 - mkl
我在pdfkit库中也发现了这个评论。我正在使用utf-8,但我不知道如何将它编码为32。 - Pietro
2
UTF-8不是适合PDF字体编码的正确方式。您应该检查当前PDF字体的编码方式。如果它是纯双字节编码(例如Identity-H),则无法使用单词间距。 - mkl
抱歉,我对PDF不是很了解,这是jsPDF中指定的内容:“由于Adobe专注于“你子集化你的字体!”,因此你不应该有一个将Unicode(UCS2 / UTF16BE)代码直接映射到字体GID的字体,但你可以使用“Identity-H”编码和自定义CIDtoGID映射来模拟Unicode代码页。然而,在流中的所有字符都被视为GID,包括BOM,这就是我们需要跳过内容文本中的BOM(即与字体相关联的文本)的原因。” - Pietro
Identity-H 是一种纯16位编码。因此,不适用单词间距。 - mkl
3个回答

9

我在Github上回答了你,根据你的建议,我将自己的调整代码写入了重构后的jsPDF中。

看看这个...

https://github.com/MrRio/jsPDF/issues/1016#issuecomment-329957940

编辑:

哦,等等,我可能可以直接回答。我认为你只需要像这样更改它:

var wordSpacing = (Math.max(0, (pdfPageWidth - textWidth) / Math.max(1, nWords - 1)) * this.internal.scaleFactor);

if (align) {
    ...                
    else if (align === 'justify') {
        var wordSpacingPerLine = [];
        for (var i = 0, len = da.length; i < len; i++) {
            wordSpacingPerLine.push(((this.internal.pageSize.width - lineWidths[i]) / (da[i].split(" ").length - 1) * k).toFixed(2));
        }
    }
    else {
        throw new Error('Unrecognized alignment option, use "center" or "right".');
    }
    prevX = x;
    text = '(' + da[0];

    let pdfPageWidth = this.internal.pageSize.width;
    let wordSpacing;
    if( align === 'justify' ) {
        text =  wordSpacingPerLine[0]  + ' Tw\n' + text;
    }
    ...
}

您需要为每一行添加特定的字间距,但最后一行除外。最后一行则是左对齐的。

以下是一个示例:

BT
/F1 16 Tf
18.4 TL
0 g
4.869500000212597 Tw
28.35 813.54 Td
(Lorem ipsum dolor sit amet, consetetur abore et dolore) Tj
3.5284444446334158 Tw
0.00 -18.40 Td
(magna aliquyam erat, sed diam voluptua. At vero eos et) Tj
2.0876000001700574 Tw
0.00 -18.40 Td
(accusam et justo duo dolores et ea rebum. Stet clita kasd) Tj
1.329500000212585 Tw
0.00 -18.40 Td
(gubergren, no sea takimata sanctus est Lorem ipsum dolor) Tj
1.329500000212585 Tw
0.00 -18.40 Td
(sit amet.) Tj
ET

1
请编辑您的答案并在此处包含它。在SO中强烈不建议链接到外部网站。 - hatef
无法,因为它是Git存储库的重构分支。但解决方案是将scaleFactor添加到wordSpace-Value中。 - Uzlopak
太好了!不确定答案是否正确,但是为努力加一分! - hatef
请在Github上查看结果: https://github.com/MrRio/jsPDF/issues/1016#issuecomment-329960894 - Uzlopak
我修改了代码,我假设你不会在一个文本调用中使用多行。 - Uzlopak
显示剩余6条评论

0

0
经过多次尝试,我已找到可行的代码解决方案:D。它还可以使用文本数组作为参数。
        } else if (align === 'justify') {
          left = x;
        }
        else {
          throw new Error(
            'Unrecognized alignment option, use "center" or "right".'
          );
        }
        prevX = x;
        text = '(' + da[0];

        var pdfPageWidth = this.internal.pageSize.width;
        var wordSpacing;
        var fontSize = this.internal.getFontSize();
        if( align === 'justify' ) {
          var nWords = da[0].trim().split(/\s+/).length;
          var textWidth = this.getStringUnitWidth(da[0]) * fontSize / k;

          wordSpacing = (Math.max(0, ((pdfPageWidth - x - marginRight) - textWidth) / Math.max(1, nWords - 1))) * k;
          // Do not justify if wordSpacing is too high
          wordSpacing = ( wordSpacing > 50 ? 0 : wordSpacing ) + ' Tw\n';

          text = wordSpacing + text;
        }

        for (var i = 1, len = da.length; i < len; i++) {
          var delta = maxLineLength - lineWidths[i];
          if (align === "center") delta /= 2;
          if (align === "justify") { // TODO: improve code duplication
            delta = 0;
            var nWords = da[i].trim().split(/\s+/).length;
            var textWidth = this.getStringUnitWidth(da[i]) * fontSize / k;

            wordSpacing = (Math.max(0, ((pdfPageWidth - x - marginRight) - textWidth) / Math.max(1, nWords - 1))) * k;
            // Do not justify if wordSpacing is too high
            wordSpacing = ( wordSpacing > 50 ? 0 : wordSpacing ) + ' Tw\n';
            text += ") Tj\n" + ((left - prevX) + delta) + " -" + leading + " Td\n" + wordSpacing + "(" + da[i];
          } else {
            // T* = x-offset leading Td ( text )
            text += ") Tj\n" + ((left - prevX) + delta) + " -" + leading + " Td (" + da[i];
          }
          prevX = left + delta;
        }
      } else {
        text = ' 0 Tw\n (' + da.join(") Tj\nT* (");
      }

这是我的 PR

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接