Determine dynamic Font for i18n while writing pdf using iText

491 Views Asked by At

My requirement is such as while generating PDF, right now i am using Arial Unicode.ttf for i18n languages including CJK.

BaseFont nationalBase = null;
Font headerFont = null;
nationalBase=BaseFont.createFont("Arial_Unicode_MS.ttf", BaseFont.IDENTITY_H, BaseFont.EMBEDDED);
headerFont = new Font(nationalBase, 10, Font.NORMAL, new Color(138,138,138));    
Paragraph p = new Paragraph("Hello Everyone 是时候了 쓰기 รูปแบบไฟล์ PDF" , headerFont);
document.add(p);

Now as you can see in String which i am writing to PDF has multiple languages,As i want to replace Arial_Unicode_MS.ttf to another font file as its licensed version.I tried to merge files of Google Noto but as this has different UPM of all fonts(like CJK has 2048 UPM and all other has 1000 UPM like Thai,Egyptian..etc) so not able to . merge Regular file with CJK.I tried to embed GNU free font but it's not giving actual feel as it's bitmap based.Now the question,Is there any facility available in iText like if i add multiple fonts as many i want and based on the character it doesn't find on first ttf file,it will get to go on for second ttf file,then third..so on till the collection does not get empty.

private static Font ArbFont = new Font("NotoNakshArabic.ttf", 18,Font.BOLD);
private static Font ScFont = new Font("NotoSansCJKSc-Regular.ttf", 12,Font.NORMAL, BaseColor.RED);
private static Font tcFont = new Font("NotoSansCJKTc-Regular.ttf", 16,Font.BOLD);
private static Font KrFont = new Font("NotoSansCJKKr-Regular.ttf", 12,Font.BOLD);

Please help on this,As i want to dynamically load a file based on the character it is in,but as i have huge file to create at a time i can't check on each character and load specific file.

1

There are 1 best solutions below

0
mkl On

The mechanism you are looking for is provided by the FontProvider class.

You start by instantiating FontProvider and adding fonts to it. Then you set this instance as provider of your Document, select one or more font family names as preferred font families, and start adding to your document:

FontProvider provider = new FontProvider();
for (String resourceName : new String[] { "NotoNaskhArabic-Regular.ttf", "NotoSansCJKkr-Regular.otf", "NotoSansCJKsc-Regular.otf", "NotoSansCJKtc-Regular.otf", "NotoSansThai-Regular.ttf " }) {
    try (   InputStream resource = getClass().getResourceAsStream(resourceName) ) {
        provider.addFont(StreamUtil.inputStreamToArray(resource));
    }
}

try (   PdfDocument pdfDoc = new PdfDocument(new PdfWriter("FontProviderForAshaKoshti.pdf"));
        Document doc = new Document(pdfDoc) ) {
    doc.setFontProvider(provider);
    doc.setFontFamily("NotoSans");

    Paragraph p = new Paragraph("Hello Everyone 是时候了 쓰기 รูปแบบไฟล์ PDF");
    doc.add(p);
}

(UseFontProvider test testFontProviderForAshaKoshti)

The result:

Screen shot

Some remarks:

  • I added the fonts from the resources. Alternatively you can of course also add arbitrary font files in your file system.
  • In addition to the fonts you mentioned, I added NotoSansThai as your example string contains Thai writing.
  • It may look like you can re-use your FontProvider across documents. That is (currently) not the case. The reason is that font subsets are created which are specific for a single Document.
  • A similar question and answer can be found here. In contrast to the situation here they use C++ and C#, not Java, and the method SetFont which meanwhile has been deprecated in favor of SetFontFamily.