Skip to content

Commit fe2dd85

Browse files
committed
Add processing of calligraphic indic and arabic fonts
DEVSIX-1881
1 parent 53b816e commit fe2dd85

File tree

6 files changed

+120
-6
lines changed

6 files changed

+120
-6
lines changed

src/main/java/com/itextpdf/html2pdf/resolver/font/DefaultFontProvider.java

Lines changed: 54 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -42,11 +42,18 @@ This file is part of the iText (R) project.
4242
*/
4343
package com.itextpdf.html2pdf.resolver.font;
4444

45+
import com.itextpdf.html2pdf.LogMessageConstant;
4546
import com.itextpdf.io.util.ResourceUtil;
4647
import com.itextpdf.io.util.StreamUtil;
48+
import com.itextpdf.layout.font.FontProvider;
49+
import com.itextpdf.layout.font.Range;
50+
import com.itextpdf.layout.font.RangeBuilder;
4751
import com.itextpdf.styledxmlparser.resolver.font.BasicFontProvider;
52+
import org.slf4j.LoggerFactory;
4853

4954
import java.io.InputStream;
55+
import java.lang.reflect.Method;
56+
import java.util.ArrayList;
5057

5158
/**
5259
* The default {@link BasicFontProvider} for pdfHTML, that, as opposed to
@@ -55,6 +62,11 @@ This file is part of the iText (R) project.
5562
*/
5663
public class DefaultFontProvider extends BasicFontProvider {
5764

65+
/**
66+
* The logger.
67+
*/
68+
private static final org.slf4j.Logger LOGGER = LoggerFactory.getLogger(DefaultFontProvider.class);
69+
5870
/** The path to the shipped fonts. */
5971
private static final String SHIPPED_FONT_RESOURCE_PATH = "com/itextpdf/html2pdf/font/";
6072

@@ -74,6 +86,13 @@ public class DefaultFontProvider extends BasicFontProvider {
7486
"FreeSerifItalic.ttf",
7587
};
7688

89+
// This range exclude Hebrew, Arabic, Syriac, Arabic Supplement, Thaana, NKo, Samaritan,
90+
// Mandaic, Syriac Supplement, Arabic Extended-A, Devanagari, Bengali, Gurmukhi, Gujarati,
91+
// Oriya, Tamil, Telugu, Kannada, Malayalam, Sinhala, Thai unicode blocks.
92+
// Those blocks either require pdfCalligraph or do not supported by GNU Free Fonts.
93+
private static final Range FREE_FONT_RANGE = new RangeBuilder()
94+
.addRange(0, 0x058F).addRange(0x0E80, Integer.MAX_VALUE).create();
95+
7796
/**
7897
* Creates a new {@link DefaultFontProvider} instance.
7998
*/
@@ -91,22 +110,51 @@ public DefaultFontProvider() {
91110
public DefaultFontProvider(boolean registerStandardPdfFonts, boolean registerShippedFreeFonts, boolean registerSystemFonts) {
92111
super(registerStandardPdfFonts, registerSystemFonts);
93112
if (registerShippedFreeFonts) {
94-
addShippedFreeFonts();
113+
addShippedFreeFonts(addCalligraphFonts());
95114
}
96115
}
97116

98117
/**
99118
* Adds the shipped free fonts.
100119
*/
101-
private void addShippedFreeFonts() {
120+
private void addShippedFreeFonts(Range rangeToLoad) {
102121
for (String fontName : SHIPPED_FONT_NAMES) {
103-
InputStream stream = ResourceUtil.getResourceStream(SHIPPED_FONT_RESOURCE_PATH + fontName);
104-
try {
122+
try (InputStream stream = ResourceUtil.getResourceStream(SHIPPED_FONT_RESOURCE_PATH + fontName)) {
105123
byte[] fontProgramBytes = StreamUtil.inputStreamToArray(stream);
106-
addFont(fontProgramBytes);
107-
} catch (Exception exc) {
124+
addFont(fontProgramBytes, null, rangeToLoad);
125+
} catch (Exception e) {
126+
LOGGER.error(LogMessageConstant.ERROR_LOADING_FONT);
108127
}
109128
}
110129
}
111130

131+
private Range addCalligraphFonts() {
132+
String methodName = "loadShippedFonts";
133+
Class<?> klass = null;
134+
try {
135+
klass = getTypographyUtilsClass();
136+
} catch (ClassNotFoundException ignored) { }
137+
if (klass != null) {
138+
try {
139+
Class[] cArg = {FontProvider.class};
140+
Method m = klass.getMethod(methodName);
141+
// an empty array of arguments is needed for autoport
142+
Object[] args = new Object[] {};
143+
ArrayList<byte[]> fontStreams = (ArrayList<byte[]>) m.invoke(cArg, args);
144+
for (byte[] font : fontStreams)
145+
addFont(font);
146+
// here we return a unicode range that excludes the loaded from the calligraph module fonts
147+
// i.e. the unicode range that is to be rendered with standard or shipped free fonts
148+
return FREE_FONT_RANGE;
149+
} catch (Exception e) {
150+
LOGGER.error(LogMessageConstant.ERROR_LOADING_FONT);
151+
}
152+
}
153+
return null;
154+
}
155+
156+
private static Class<?> getTypographyUtilsClass() throws ClassNotFoundException {
157+
String typographyClassFullName = "com.itextpdf.typography.util.TypographyShippedFontsUtil";
158+
return Class.forName(typographyClassFullName);
159+
}
112160
}
Lines changed: 42 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,42 @@
1+
package com.itextpdf.html2pdf;
2+
3+
import com.itextpdf.kernel.utils.CompareTool;
4+
import com.itextpdf.test.ExtendedITextTest;
5+
import com.itextpdf.test.annotations.LogMessage;
6+
import com.itextpdf.test.annotations.LogMessages;
7+
import org.junit.Assert;
8+
import org.junit.BeforeClass;
9+
import org.junit.Test;
10+
11+
import java.io.File;
12+
import java.io.IOException;
13+
14+
// Actually the results are invalid because there is no pdfCalligraph.
15+
// But we'd like to test how Free Sans works for a specific scripts.
16+
public class FontProviderTest extends ExtendedITextTest {
17+
public static final String sourceFolder = "./src/test/resources/com/itextpdf/html2pdf/FontProviderTest/";
18+
public static final String destinationFolder = "./target/test/com/itextpdf/html2pdf/FontProviderTest/";
19+
20+
private static final String TYPOGRAPHY_WARNING = "Cannot find pdfCalligraph module, which was implicitly required by one of the layout properties";
21+
22+
@BeforeClass
23+
public static void beforeClass() {
24+
createDestinationFolder(destinationFolder);
25+
}
26+
27+
@Test
28+
@LogMessages(messages = {
29+
@LogMessage(messageTemplate = TYPOGRAPHY_WARNING, count = 14)
30+
})
31+
public void hebrewTest() throws IOException, InterruptedException {
32+
HtmlConverter.convertToPdf(new File(sourceFolder + "hebrew.html"), new File(destinationFolder + "hebrew.pdf"));
33+
Assert.assertNull(new CompareTool().compareByContent(destinationFolder + "hebrew.pdf", sourceFolder + "cmp_hebrew.pdf", destinationFolder, "diffHebrew_"));
34+
}
35+
36+
@Test
37+
public void devanagariTest() throws IOException, InterruptedException {
38+
HtmlConverter.convertToPdf(new File(sourceFolder + "devanagari.html"), new File(destinationFolder + "devanagari.pdf"));
39+
Assert.assertNull(new CompareTool().compareByContent(destinationFolder + "devanagari.pdf", sourceFolder + "cmp_devanagari.pdf", destinationFolder, "diffDevanagari_"));
40+
}
41+
42+
}
Binary file not shown.
Binary file not shown.
Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,12 @@
1+
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.1//EN" "http://www.w3.org/TR/xhtml11/DTD/xhtml11.dtd">
2+
<html>
3+
<head></head>
4+
<body style="font-family: Times New Roman,Times,serif;">
5+
<h1>Result is invalid because there is no pdfCalligraph!</h1>
6+
<div>
7+
<b>अनुच्छेद १. सभी मनुष्यों को गौरव और अधिकारों के मामले में जन्मजात स्वतन्त्रता और समानता प्राप्त है । उन्हें बुद्धि और अन्तरात्मा की देन प्राप्त है और परस्पर उन्हें भाईचारे के भाव से बर्ताव करना चाहिए ।</b>
8+
9+
अनुच्छेद २. सभी को इस घोषणा में सन्निहित सभी अधिकारों और आज़ादियों को प्राप्त करने का हक़ है और इस मामले में जाति, वर्ण, लिंग, भाषा, धर्म, राजनीति या अन्य विचार-प्रणाली, किसी देश या समाज विशेष में जन्म, सम्पत्ति या किसी प्रकार की अन्य मर्यादा आदि के कारण भेदभाव का विचार न किया जाएगा । इसके अतिरिक्त, चाहे कोई देश या प्रदेश स्वतन्त्र हो, संरक्षित हो, या स्त्रशासन रहित हो या परिमित प्रभुसत्ता वाला हो, उस देश या प्रदेश की राजनैतिक, क्षेत्रीय या अन्तर्राष्ट्रीय स्थिति के आधार पर वहां के निवासियों के प्रति कोई फ़रक़ न रखा जाएगा ।
10+
</div>
11+
</body>
12+
</html>
Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,12 @@
1+
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.1//EN" "http://www.w3.org/TR/xhtml11/DTD/xhtml11.dtd">
2+
<html>
3+
<head></head>
4+
<body style="font-family: Times New Roman,Times,serif; direction: rtl;">
5+
<h1>Result is invalid because there is no pdfCalligraph!</h1>
6+
<div>
7+
<b>סעיף א. כל בני אדם נולדו בני חורין ושווים בערכם ובזכויותיהם. כולם חוננו בתבונה ובמצפון, לפיכך חובה עליהם לנהוג איש ברעהו ברוח של אחוה.</b>
8+
9+
סעיף ב. כל אדם זכאי לזכויות ולחרויות שנקבעו בהכרזש זו ללא הפליה כלשהיא מטעמי גזע, צבע, מין, לשון, דח, דעה פוליטית או דעה בבעיות אחרות, בגלל מוצא לאומי או חברתי, קנין, לידה או מעמד אחר. גדולה מזו, לא יופלה אדם על פי מעמדה המדיני, על פי סמכותה או על פי מעמדה הבינלאומי של המדינה או הארץ שאליה הוא שייך, דין שהארץ היא עצמאית, ובין שהיא נתונה לנאמנות, בין שהיא נטולת שלטון עצמי ובין שריבונותה מוגבלת כל הגבלה אחרת.
10+
</div>
11+
</body>
12+
</html>

0 commit comments

Comments
 (0)