JsPDF оправдывает текст

Я пытаюсь применить некоторые изменения в библиотеке 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

После многих попыток я нашел решение рабочего кода: 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

Ответ 2

Я ответил вам на 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

Ответ 3

При использовании пользовательского шрифта (ttf и т.д.) Текст Justify можно сделать с помощью javascript, чтобы поместить все слова в правильное положение. См. fooobar.com/info/17761367/...