[ 
https://issues.apache.org/jira/browse/PDFBOX-3992?page=com.atlassian.jira.plugin.system.issuetabpanels:all-tabpanel
 ]

Tilman Hausherr resolved PDFBOX-3992.
-------------------------------------
       Resolution: Fixed
    Fix Version/s: 3.0.0
                   2.0.9

> Implement show text with positioning operator (TJ)
> --------------------------------------------------
>
>                 Key: PDFBOX-3992
>                 URL: https://issues.apache.org/jira/browse/PDFBOX-3992
>             Project: PDFBox
>          Issue Type: Improvement
>          Components: PDModel
>            Reporter: Dan Fickling
>            Assignee: Tilman Hausherr
>             Fix For: 2.0.9, 3.0.0
>
>         Attachments: justify-example.pdf, showtextwithpositioning.patch
>
>
> Why: The TJ operator is required to properly implement text justification in 
> unicode fonts. The word spacing operator (Tw) is not sufficient because of 
> note[1] from the PDF specification.
> Github user backslash47 has provided a basic implementation if that is of any 
> help:
> https://github.com/backslash47/pdfbox/commit/3c528295b16445e58dc9fe895f78384221452be2
> Thanks,
> Daniel.
> [1] Note: Word spacing is applied to every occurrence of the single-byte 
> character code 32 in a string when using a simple font or a composite font 
> that defines code 32 as a single-byte code. It does not apply to occurrences 
> of the byte value 32 in multiple-byte codes. 
> Example code:
> {code:java}
> import java.io.InputStream;
> import java.util.ArrayList;
> import java.util.List;
> import org.apache.pdfbox.pdmodel.PDDocument;
> import org.apache.pdfbox.pdmodel.PDPage;
> import org.apache.pdfbox.pdmodel.PDPageContentStream;
> import org.apache.pdfbox.pdmodel.PDPageContentStream.AppendMode;
> import org.apache.pdfbox.pdmodel.common.PDRectangle;
> import org.apache.pdfbox.pdmodel.font.PDFont;
> import org.apache.pdfbox.pdmodel.font.PDType0Font;
> import org.apache.pdfbox.util.Matrix;
> public class TextWithPositioningExample {
>       public static void main(String[] args) throws Exception {
>               doIt("Hello World, this is a test!", "justify-example.pdf");
>       }
>       /**
>        * This example shows how to justify a string using the 
> showTextWithPositioning method.
>        * First only spaces are adjusted, and then every letter.
>        */
>       public static void doIt(String message, String outfile) throws 
> Exception {
>               // the document
>               try (PDDocument doc = new PDDocument();
>                        InputStream is = 
> PDDocument.class.getResourceAsStream("/org/apache/pdfbox/resources/ttf/LiberationSans-Regular.ttf"))
>  {
>                       final float FONT_SIZE = 20.0f;
>                       // Page 1
>                       PDFont font = PDType0Font.load(doc, is, true);
>                       //PDFont font = PDType1Font.COURIER;
>                       PDPage page = new PDPage(PDRectangle.A4);
>                       doc.addPage(page);
>                       
>                       // Get the non-justified string width in text space 
> units.
>                       float stringWidth = font.getStringWidth(message) * 
> FONT_SIZE;
>                       
>                       // Get the string height in text space units.
>                       float stringHeight = 
> font.getFontDescriptor().getFontBoundingBox().getHeight() * FONT_SIZE;
>                       
>                       // Get the width we have to justify in.
>                       PDRectangle pageSize = page.getMediaBox();
>                       
>                       PDPageContentStream contentStream = new 
> PDPageContentStream(doc,
>                                       page, AppendMode.OVERWRITE, false);
>               
>                       contentStream.beginText();
>                       contentStream.setFont(font, FONT_SIZE);
>                       
>                       // Start at top of page.
>                       
> contentStream.setTextMatrix(Matrix.getTranslateInstance(0, 
> pageSize.getHeight() - stringHeight / 1000f));
>                       
>                       // First show non-justified.
>                       contentStream.showText(message);
>                       
>                       // Move to next line.
>                       
> contentStream.setTextMatrix(Matrix.getTranslateInstance(0, 
> pageSize.getHeight() - ((stringHeight / 1000f) * 2)));
>                       
>                       // Now show word justified.
>                       // The space we have to make up, in text space units.
>                       float justifyWidth = ((pageSize.getWidth() * 1000f) - 
> (stringWidth));
>                       
>                       List<Object> text = new ArrayList<>();
>                       String[] parts = message.split("\\s");
>                       
>                       float spaceWidth = (justifyWidth / (parts.length - 1)) 
> / FONT_SIZE;
>                       for (int i = 0; i < parts.length; i++) {
>                               if (i != 0) {
>                                       text.add(" ");
>                                       // Positive values move to the left, 
> negative to the right.
>                                       text.add(Float.valueOf(-spaceWidth));
>                               }
>                               text.add(parts[i]);
>                       }
>                       contentStream.showTextWithPositioning(text.toArray());
>                       
> contentStream.setTextMatrix(Matrix.getTranslateInstance(0, 
> pageSize.getHeight() - ((stringHeight / 1000f) * 3)));
>                       
>                       // Now show letter justified.
>                       text = new ArrayList<>();
>                       justifyWidth = ((pageSize.getWidth() * 1000f) - 
> stringWidth);
>                       float extraLetterWidth = (justifyWidth / 
> (message.codePointCount(0, message.length()) - 1)) / FONT_SIZE;
>                       
>                       for (int i = 0; i < message.length();) {
>                               if (i != 0) {
>                                       
> text.add(Float.valueOf(-extraLetterWidth));
>                               }
>                               
>                               
> text.add(String.valueOf(Character.toChars(message.codePointAt(i))));
>                               
>                               i += 
> Character.charCount(message.codePointAt(i));
>                       }
>                       contentStream.showTextWithPositioning(text.toArray());;
>                       
>                       // Finish up.
>                       contentStream.endText();
>                       contentStream.close();
>                       doc.save(outfile);
>               }
>       }
> }
> {code}



--
This message was sent by Atlassian JIRA
(v6.4.14#64029)

---------------------------------------------------------------------
To unsubscribe, e-mail: [email protected]
For additional commands, e-mail: [email protected]

Reply via email to