ralfstuckert/pdfbox-layout

Custom Fonts in Document API

Closed this issue · 10 comments

I was wondering if it was possible to both use the Document API and load custom Fonts (such as Arial) to use. I know that it's possible with pdfbox so I could use the Text API and load the fonts that way, but I believe certain markup doesn't seem to work in only the Text API: underline, strike through, lists, and etc.

Please let me know if I totally missed something and there is a way to load custom fonts or if I'm not using the markup correctly in the Text API.

Maybe I'm missing your point, but the following works for me. All you need to load a font with PDFBox is the PDDocument. With the low-level API you create that on your own. Using the document API you can access the the PDDocument with document.getPDDocument(). Here is a simple hello world:

Document document = new Document(40, 60, 40, 60);
PDFont font = PDTrueTypeFont.loadTTF(document.getPDDocument(), "Candara.ttf");

Paragraph paragraph = new Paragraph();
paragraph.addText("Hello Document\n\n", 20, font);
document.add(paragraph);

final OutputStream outputStream = new FileOutputStream("hellodoc.pdf");
document.save(outputStream);

For using markup you have to provide fonts for plain, bold, italic and bold-italic:

PDFont font = PDTrueTypeFont.loadTTF(document.getPDDocument(), "Candara.ttf");
PDFont fontBold = PDTrueTypeFont.loadTTF(document.getPDDocument(), "Candarab.ttf");
PDFont fontItalic = PDTrueTypeFont.loadTTF(document.getPDDocument(), "Candarai.ttf");
PDFont fontBoldItalic = PDTrueTypeFont.loadTTF(document.getPDDocument(), "Candaraz.ttf");

paragraph.addMarkup("Hello *bold* _italic_ *_bold-italic_* Document", 20, font, fontBold, fontItalic, fontBoldItalic);

Does that fit your needs, or am I completely missing your point?

You got it, I just needed the getDocument method to load the fonts in the Document API.

I have one more question for you that I think I know the answer to but still worth asking:

Is it possible to use markup like underscore, lists (ordered and unordered), and strike through with the low level API? I've used the markup, it seems to get extracted from the string, but it doesn't get created. I'm guessing that markup only works with the document API?

Please let me know if there is anything left, so I may close this issue
Regards
Ralf

Ok, point for you. The annotation based markup will not be rendered out of the box (underline and hyperlinks). I will extend the example by that. Stay tuned

Cool, thanks.

Yea, I saw that example but it was only using bold, italic, and bolditalic markup.

I was trying to use the underscore (), strikethrough ({0.25:}), and lists markup (-* and -#). I'll keep my eyes peeled for the example.

Just wanted to thank you again for a great library and for responding!

I think I figured out what the issue was. As far as I could tell after some digging around, was that the drawlistener is responsible for drawing the annotation based markup like underscore and hyperlink.

I needed to instantiate an Annotation drawlistener and for that I needed a DrawContext. I created a class that implemented the interface and had the 3 get methods for the pdfbox objects.

I then passed the drawlistener into the drawText method of TextFlow and thought that would do the trick. It didn't and after some more digging I realized that I needed to call some of the listener methods like beforePage, afterPage, and afterRender which did most of the work.

I tried doing that but realized that for some reason beforePage and afterPage took a RenderContext as a parameter but didn't even use it because it used the it's private DrawContext instead. It had to use that as a parameter because of the Renderer interface it implemented. RenderContext needed a Document as a parameter so I couldn't use that because I'm just trying to is the basic Text API.

I finally got around this by writing my own custom listener that extended DrawListener and not the Renderer interface. Then I simply took out the RenderContext argument from the afterPage and beforePage context and used that as my listener. This fixed my issues and now I'm able to use the underscore, hyperlink, lists, and other annotations.

I think that in order for the current setup and markup to work in the library for the Text API you'll need to take out the RenderContext arguments so that it doesn't have to rely on something from the elements/layout API.

I rambled a little but I hope I provided enough detail to explain what I ran into while trying to figure it out.

Sorry, I couldn't make it yesterday evening, but you already got it right. I have updated the LowLevelText example, see https://github.com/ralfstuckert/pdfbox-layout/blob/master/examples/LowLevelText.java. The point with the RenderContext is quite weird, it is far about time for a refactoring to clean things up, but I'm a bit out of time for that :-\

Anything left open, or may I close this issue?

Sorry, this issue is done. Thank you for your help!