Skip to main content
Skip table of contents

pdfCalligraph: New types of GPOS lookup

Background:

The Glyph Positioning table (GPOS) provides precise control over glyph placement for sophisticated text layout and rendering in each script and language system that a font supports. To further expand its ability to support advanced glyph positioning techniques, iText is working on supporting Glyph Positioning (GPOS).

GPOS implementation will improve how iText renders feature-associated lookups which contain data for the feature. This new development will ensure that advanced adjustment positioning for complex scripts and glyphs is done properly. For instance, some languages (such as Arabic or Myanmar) require complex adjustment positioning of glyphs to have the font display as it should.

In previous versions iText will in some cases not guarantee correct results if the selected font is using unimplemented GPOS table features. However, in iText Core release 7.2.0 and Calligraph 3.0.0 support was added for GPOS lookup type 1 and subtype 2.

Code Snippet:

In the following code snippet, we take an input text written in Myanmar script and write it into a PDF using iText:

JAVA

JAVA
import com.itextpdf.io.font.PdfEncodings;
import com.itextpdf.kernel.font.PdfFont;
import com.itextpdf.kernel.font.PdfFontFactory;
import com.itextpdf.kernel.pdf.PdfDocument;
import com.itextpdf.kernel.pdf.PdfWriter;
import com.itextpdf.layout.Document;
import com.itextpdf.layout.element.Paragraph;

import com.itextpdf.layout.properties.BaseDirection;
import com.itextpdf.layout.properties.TextAlignment;
import com.itextpdf.licensing.base.LicenseKey;
import java.io.FileInputStream;
import java.io.IOException;

public class GposLookupExample {
    private static String TEXT = "ဗမာမှာ လူများစုဗမာမျိုး နွယ်စု၏ ခေါ် ရာတွင် တရားဝင်ခေါ် သော အသုံး ဖြ စ်သည်။ အင်္ဂလိပ်လက်အော က်";
    private static String FONT = "src/main/resources/font/NotoSansMyanmar-Regular.ttf";
    private static String DEST = "target/result.pdf";

    public static void main(String[] args) throws IOException {
        manipulatePdf(DEST);
    }

    public static void manipulatePdf(String dest) throws IOException {
        LicenseKey.loadLicenseFile(new FileInputStream("license/license.json"));

        Document document = new Document(new PdfDocument(new PdfWriter(dest)));
        PdfFont font = PdfFontFactory.createFont(FONT,
                                                 PdfEncodings.IDENTITY_H, PdfFontFactory.EmbeddingStrategy.FORCE_EMBEDDED);
        Paragraph paragraph = new Paragraph(TEXT)
                .setBaseDirection(BaseDirection.LEFT_TO_RIGHT)
                .setTextAlignment(TextAlignment.LEFT);
        font.setSubset(false);

        paragraph.setFont(font);
        document.add(paragraph);

        document.close();
    }
}

C#

C#
using System.IO;
using iText.IO.Font;
using iText.Kernel.Font;
using iText.Kernel.Pdf;
using iText.Layout;
using iText.Layout.Element;
using iText.Layout.Properties;
using iText.Licensing.Base;

namespace GPOS
{
    internal class GposLookupExample
    {
        private static string TEXT =
            "ဗမာမှာ လူများစုဗမာမျိုး နွယ်စု၏ ခေါ် ရာတွင် တရားဝင်ခေါ် သော အသုံး ဖြ စ်သည်။ အင်္ဂလိပ်လက်အော က်";

        private static string FONT = "NotoSansMyanmar-Regular.ttf";
        private static string DEST = "result.pdf";

        public static void Main(string[] args)
        {
            ManipulatePdf(DEST);
        }

        public static void ManipulatePdf(string dest)
        {
            LicenseKey.LoadLicenseFile(new FileStream("license.json",
                FileMode.Open));
            using (var document = new Document(new PdfDocument(new PdfWriter(dest))))
            {
                PdfFont font = PdfFontFactory.CreateFont(FONT, PdfEncodings.IDENTITY_H,
                    PdfFontFactory.EmbeddingStrategy.FORCE_EMBEDDED);
                Paragraph paragraph = new Paragraph(TEXT).SetBaseDirection(BaseDirection.LEFT_TO_RIGHT)
                    .SetTextAlignment(TextAlignment.LEFT);
                font.SetSubset(false);
                paragraph.SetFont(font);
                document.Add(paragraph);
            }
        }
    }
}

The resulting text matches the expected result shown in Figure 1:

Figure 1

However, the text from previous versions shows the results depicted in Figure 2 below:

Figure 2

You can notice the difference in results by comparing the images above, where you can see glyphs being misplaced in the second image.

Resources:

Right-click the link below and select "Save link as..." to download.

result.zip


JavaScript errors detected

Please note, these errors can depend on your browser setup.

If this problem persists, please contact our support.