You are viewing a plain text version of this content. The canonical link for it is here.
Posted to dev@pdfbox.apache.org by "Tilman Hausherr (JIRA)" <ji...@apache.org> on 2017/11/08 20:48:00 UTC
[jira] [Resolved] (PDFBOX-3992) Implement show text with
positioning operator (TJ)
[ 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: dev-unsubscribe@pdfbox.apache.org
For additional commands, e-mail: dev-help@pdfbox.apache.org