【问题标题】:jsPDF justify textjsPDF 对齐文本
【发布时间】:2018-02-21 04:37:24
【问题描述】:

我正在尝试对 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

是否存在编码问题?

感谢您的帮助。

【问题讨论】:

  • 使用哪种字体编码?根据规范“当使用将代码32定义为单字节代码的简单字体或复合字体时,应将字间距应用于字符串中每个出现的单字节字符代码32。不应适用于多字节代码中出现的字节值 32。" 如果您的编码不将空格字形编码为单个字节 0x20,则不会按需要应用字间距。
  • 我也在 pdfkit 库上找到了这条评论。我正在使用 utf-8,但我不知道如何将其设为 32。
  • UTF-8 不是正确的 PDF 字体编码。您应该检查当前 PDF 字体的编码。如果是例如纯两字节编码(例如 Identity-H),不能使用字间距。
  • 抱歉,我对 PDF 了解不多,这是 jsPDF 中指定的内容:“由于 Adob​​e 专注于“您的字体子集!”您不应该拥有映射的字体直接将Unicode(UCS2 / UTF16BE)代码转换为字体GID,但您可以使用“Identity-H”编码和模仿Unicode代码页的自定义CIDtoGID映射来伪造它。但是,流中的所有字符都被视为GID,包括BOM ,这就是我们需要在内容文本中跳过 BOM 的原因(即与字体相关联的 BOM)。”
  • Identity-H 是纯 16 位编码。因此,不应用字间距。

标签: javascript pdf jspdf


【解决方案1】:

当使用自定义字体(ttf 等)时,可以使用 javascript 对文本进行对齐,以将所有单词放置在正确的位置。见stackoverflow justify text with custom font

【讨论】:

    【解决方案2】:

    经过多次尝试,我找到了有效的代码解决方案: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

    【讨论】:

      【解决方案3】:

      我在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;
          }
          ...
      }
      

      您必须为除最后一行之外的每一行添加特定的 WordSpacing。最后一行然后左对齐。

      这里是一个例子:

      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
      

      【讨论】:

      • 请编辑您的答案并将其包含在此处。在 SO 中强烈建议不要链接到外部网站。
      • 不能,因为它是 git repo 的重构分支。但解决方案是将 scaleFactor 添加到 wordSpace-Value。
      • 太棒了!不确定答案是否正确,但 +1 表示努力!
      • 这正是我想要做的,我一定错过了什么。 (Math.max(0, (pdfPageWidth - textWidth) / Math.max(1, nWords - 1)) / this.getStringUnitWidth(' ') * fontSize / this.internal.scaleFactor);
      • 但是为什么要计算this.getStringUnitWidth的Space乘以fontSize呢?这没有任何意义。 WordSpace 是 Space 的宽度。所以: 1.你计算行的每个单词的宽度并总结起来。 2. 从线的宽度中减去总和。这是该行中所有单词的单词空间。 3. 现在你将它除以你为空格留下的宽度除以单词数 -1。 4. 现在将它与 scaleFactor 相乘 5. 将结果设置为该特定行的 wordSpace
      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2016-05-05
      • 2019-10-24
      • 2017-07-28
      • 1970-01-01
      • 2020-07-12
      • 2015-04-08
      相关资源
      最近更新 更多