Helvetica a Greek alphabet

415 views
Skip to first unread message

rox...@gmail.com

unread,
Apr 6, 2021, 5:45:25 AM4/6/21
to Flying Saucer Users
Hello,
By setting the Helvetica font, the characters of the Greek alphabet are not represented on the PDF. While changing the font Arial or Times New Roman the characters are represented correctly.

Is there any workoround?

Rocco

<div><span style="font-family: Helvetica, Arial, sans-serif;"><strong><span style="font-size: 16pt;">&para;&micro;&alpha;&beta;&omega;&hearts;&micro;</span></strong></span></div>
<div>

lukas....@gmail.com

unread,
Apr 10, 2021, 4:15:31 AM4/10/21
to Flying Saucer Users
Hi Rocco,

this is probably caused by FlyingSaucer using default bundled latin-1. 
You might need to provide your custom font.

Have a great day

Lukas

rox...@gmail.com

unread,
Apr 10, 2021, 12:56:14 PM4/10/21
to Flying Saucer Users
Hi @Lukas,
thanks for the help

You mean this?

import com.lowagie.text.pdf.BaseFont; 

ITextRenderer renderer = new ITextRenderer(); 
FontResolver resolver = renderer.getFontResolver(); 
resolver.addFont ( "C:\\WINNT\\Fonts\\ARIALUNI.TTF", BaseFont.IDENTITY_H, BaseFont.NOT_EMBEDDED );

I tried forcing the embedding of helvetica but it still doesn't work. I have tried various types of fonts downloaded from the web. But they are not really added. If I try Arial it works.

But i found this code in ITextFontResolver:

    private static Map createInitialFontMap() {
        HashMap result = new HashMap();

        try {
            addCourier(result);
            addTimes(result);
            addHelvetica(result);
            addSymbol(result);
            addZapfDingbats(result);

            // Try and load the iTextAsian fonts
            if(ITextFontResolver.class.getClassLoader().getResource("com/lowagie/text/pdf/fonts/cjkfonts.properties") != null) {
                addCJKFonts(result);
            }
        } catch (DocumentException e) {
            throw new RuntimeException(e.getMessage(), e);
        } catch (IOException e) {
            throw new RuntimeException(e.getMessage(), e);
        }

        return result;
    }

And this

 private static BaseFont createFont(String name) throws DocumentException, IOException {
        return ITextFontResolver.createFont(name, "winansi", true);
    }

I try to overwrite this.

Have a great day

Rocco

rox...@gmail.com

unread,
Apr 11, 2021, 2:00:17 PM4/11/21
to Flying Saucer Users
Hello,
I did try to extend ITextFontResolver (9.0.9) to override some methods but I couldn't. ITextFontResolver contains only private fields and too much static references.
So I moved on to a rougher approach.

public class TestPdf {

private static final String FILE_IN = "src/test/resources/borderRadiusWithBorderWidthZero.html";
private static final String FILE_OUT = "src/test/resources/file.pdf";
private static final String FONSTS = "src/test/resources/fonts";

@Test
public void buildHelvetica() throws IOException, DocumentException, NoSuchFieldException, SecurityException, IllegalArgumentException, IllegalAccessException {
ITextRendererExt renderer = new ITextRendererExt();
ITextFontResolver fontRes = renderer.getFontResolver();
Field fontFagliesField = ITextFontResolver.class.getDeclaredField("_fontFamilies");
fontFagliesField.setAccessible(true);
Map<String, ?> fontFamiliesMap = (Map<String, ?>) fontFagliesField.get(fontRes);
fontFamiliesMap.remove("Helvetica");
renderer.addFontDirectory(renderer.getFontResolver(), FONSTS, true);
renderer.setDocAuthor("rocco");
renderer.setDocLanguage("ita");
renderer.setDocument(FILE_IN);
renderer.setPDFXConformance(0);
doRenderToPDF(renderer, FILE_OUT);
}

private static void doRenderToPDF(ITextRenderer renderer, String pdf) throws IOException, DocumentException {
try(OutputStream os = new FileOutputStream(pdf)) {
renderer.layout();
renderer.createPDF(os);
}
}
}

So removing Helvetica from the  _fontFamilies map, all the Greek characters in the html appeared.
(except the &hearts; in position 9)

GreekFont.PNG

Have a great day

Rocco

Lukas Zaruba

unread,
Apr 11, 2021, 2:33:14 PM4/11/21
to flying-sa...@googlegroups.com
Hey,

I’m pretty sure that adding the font using the snippet I pointed to you earlier worked like a charm incl. non latin chars. If I remember correctly, I embedded the fonts (…BaseFont.NOT_EMBEDDED…). You can give it a try. Following is the working snippet I used before. The fonts are loaded dynamically from other sources thus reading and copying of files, you can ignore that part.

ITextRenderer renderer = new ITextRenderer(dpi, 1);
service.getFonts().forEach(file -> {
Font font = file.getFont();
if (font.getFilename().endsWith(FontsService.TTF_SUFFIX) || font.getFilename().endsWith(FontsService.OTF_SUFFIX)) {
try {
Path temp = Files.createTempFile("temp", font.getFilename().substring(font.getFilename().lastIndexOf(".")));
try (OutputStream output = Files.newOutputStream(temp);
InputStream input = file.getResource().getInputStream()) {
IOUtils.copy(input, output);
}
renderer.getFontResolver().addFont(temp.toString(), font.getEncoding(), font.isEmbedd());
downloadedFonts.add(temp);
} catch (DocumentException | IOException e) {
getLogger().error("Error occurred while adding font to PDF file", e);
}
}
});
ITextUserAgent ua = new ITextUserAgent(renderer.getOutputDevice()) {

@Override
protected InputStream resolveAndOpenStream(String uri) {
throw new UnsupportedOperationException();
}

@Override
public String resolveURI(String uri) {
return uri;
}

};
ua.setSharedContext(renderer.getSharedContext());
renderer.getSharedContext().setUserAgentCallback(ua);
renderer.setDocumentFromString(xml);
renderer.layout();
renderer.createPDF(os);


LZ


<GreekFont.PNG>
-- 
You received this message because you are subscribed to a topic in the Google Groups "Flying Saucer Users" group.
To unsubscribe from this topic, visit https://groups.google.com/d/topic/flying-saucer-users/mO1QFqpg3pk/unsubscribe.
To unsubscribe from this group and all its topics, send an email to flying-saucer-u...@googlegroups.com.
To view this discussion on the web visit https://groups.google.com/d/msgid/flying-saucer-users/21e6249b-c9ab-4358-918c-9319632add9bn%40googlegroups.com.
<GreekFont.PNG>

rox...@gmail.com

unread,
Apr 12, 2021, 4:03:24 PM4/12/21
to Flying Saucer Users
Hy,
This strange behavior is a characteristic of Helvetica. Other fonts like Arial or Times New Roman I have no problems.

For my tests, I used these font files:

Rocco

import java.io.ByteArrayInputStream;
import java.io.File;
import java.io.FileOutputStream;
import java.io.OutputStream;
import java.lang.reflect.Field;
import java.nio.charset.StandardCharsets;
import java.util.Map;

import javax.xml.parsers.DocumentBuilder;
import javax.xml.parsers.DocumentBuilderFactory;

import org.junit.Test;
import org.w3c.dom.Document;
import org.xhtmlrenderer.pdf.ITextFontResolver;
import org.xhtmlrenderer.pdf.ITextRenderer;
import org.xhtmlrenderer.resource.FSEntityResolver;

import com.lowagie.text.pdf.BaseFont;

public class TestPdf2 {

private static final String FILE_OUT = "src/test/resources/file.pdf";
private static final String FONT_DIR = "src/test/resources/fonts/";
private static final String[] FONT_FILES = {  //
"Helvetica.ttf", "Helvetica-Bold.ttf", //
"Helvetica-BoldOblique.ttf","helvetica-compressed-5871d14b6903a.otf", // 
"helvetica-light-587ebe5a59211.ttf", "Helvetica-Oblique.ttf", //
"helvetica-rounded-bold-5871d05ead8de.otf" };

@Test
public void buildHelvetica() throws Exception {
ITextRenderer renderer = new ITextRenderer();
ITextFontResolver fontRes = renderer.getFontResolver();
// Field fontFagliesField = ITextFontResolver.class.getDeclaredField("_fontFamilies");
// fontFagliesField.setAccessible(true);
// Map<String, ?> fontFamiliesMap = (Map<String, ?>) fontFagliesField.get(fontRes);
// fontFamiliesMap.remove("Helvetica");
loadFont(fontRes);
renderer.setDocument(getSampleDocument(), null);
doRenderToPDF(renderer, FILE_OUT);
}

private static void loadFont(ITextFontResolver poF) throws Exception {
for (String lsFontFile : FONT_FILES) {
File lfFile = new File(FONT_DIR + lsFontFile);
poF.addFont(lfFile.getAbsolutePath(), BaseFont.IDENTITY_H, BaseFont.NOT_EMBEDDED);
}
}

private static void doRenderToPDF(ITextRenderer renderer, String pdf) throws Exception {
try (OutputStream os = new FileOutputStream(pdf)) {
renderer.layout();
renderer.createPDF(os);
}
}

private static Document getSampleDocument() throws Exception {
String lsSampleGreekDoc = //
"<!DOCTYPE html PUBLIC \"-//W3C//DTD XHTML 1.0 Strict//EN\" \"http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd\">" //
+ "<html xmlns=\"http://www.w3.org/1999/xhtml\">\r\n" //
+ "<head>\r\n" //
+ "<meta http-equiv=\"Content-Type\" content=\"text/html; charset=UTF-8\" />\r\n" //
+ "<title>Test</title>\r\n"//
+ "</head>\r\n" //
+ "<body>\r\n" //
+ "<div style=\"font-family: Helvetica; font-size: 16pt;\">\r\n" //
+ " <del>Helvetica:</del>1&para; 2&micro; 3&alpha; 4&beta; 5&delta; 6&epsilon; " //
+ "7&zeta; 8&omega; 9&hearts; 10&micro; 11&Theta; 12&Xi; 13&Sigma;\r\n" //
+ "</div>\r\n" //
+ "</body>\r\n" //
+ "</html>"; //
DocumentBuilder loDocumentBuilderXml = DocumentBuilderFactory.
newInstance().newDocumentBuilder();
loDocumentBuilderXml.setEntityResolver(FSEntityResolver.instance());
ByteArrayInputStream loArrayInputStream = new ByteArrayInputStream(lsSampleGreekDoc.getBytes(StandardCharsets.UTF_8));
return loDocumentBuilderXml.parse(loArrayInputStream);
}

}
Reply all
Reply to author
Forward
0 new messages