javascriptpdfjspdf

jsPDF justify text


I'm trying to apply some changes on jsPDF library to be able to justify text.

I'm having trouble to find the right value for Tw (word spacing).

In jspdf.js (L:1413) I have added this code:

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

The idea was to extract the space width by doing (pageWidth - textWidth) / numberOfWords -1. I can't get the correct word space.

Output example

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

Is there an encoding problem?

Thanks for your help.


Solution

  • After many tries I have found the working code solution :D. It works also with array of text as param.

            } 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* (");
          }
    

    Here is my PR