|
5 | 5 | import com.itextpdf.io.font.TrueTypeFont;
|
6 | 6 | import com.itextpdf.io.font.otf.Glyph;
|
7 | 7 | import com.itextpdf.io.font.otf.GlyphLine;
|
| 8 | +import com.itextpdf.kernel.color.Color; |
| 9 | +import com.itextpdf.kernel.font.PdfFont; |
| 10 | +import com.itextpdf.kernel.font.PdfType0Font; |
8 | 11 | import com.itextpdf.kernel.geom.Rectangle;
|
9 | 12 | import com.itextpdf.kernel.pdf.PdfDocument;
|
10 | 13 | import com.itextpdf.kernel.pdf.PdfName;
|
11 | 14 | import com.itextpdf.kernel.pdf.canvas.CanvasArtifact;
|
12 | 15 | import com.itextpdf.kernel.pdf.canvas.PdfCanvas;
|
13 |
| -import com.itextpdf.kernel.color.Color; |
14 |
| -import com.itextpdf.kernel.font.PdfFont; |
15 |
| -import com.itextpdf.kernel.font.PdfType0Font; |
16 | 16 | import com.itextpdf.kernel.pdf.canvas.PdfCanvasConstants;
|
17 | 17 | import com.itextpdf.kernel.pdf.tagutils.IAccessibleElement;
|
18 | 18 | import com.itextpdf.kernel.pdf.tagutils.PdfTagStructure;
|
|
27 | 27 | import com.itextpdf.layout.layout.TextLayoutResult;
|
28 | 28 | import com.itextpdf.layout.splitting.ISplitCharacters;
|
29 | 29 |
|
30 |
| -import java.lang.reflect.Constructor; |
31 |
| -import java.lang.reflect.Method; |
32 |
| -import java.util.ArrayList; |
| 30 | +import java.util.Collection; |
| 31 | +import java.util.EnumMap; |
| 32 | +import java.util.HashMap; |
33 | 33 | import java.util.List;
|
34 |
| - |
35 |
| -import org.slf4j.Logger; |
36 |
| -import org.slf4j.LoggerFactory; |
| 34 | +import java.util.Map; |
37 | 35 |
|
38 | 36 | /**
|
39 | 37 | * This class represents the {@link IRenderer renderer} object for a {@link Text}
|
@@ -323,14 +321,47 @@ public void applyOtf() {
|
323 | 321 | Character.UnicodeScript script = getProperty(Property.FONT_SCRIPT);
|
324 | 322 | Property.FontKerning fontKerning = getProperty(Property.FONT_KERNING);
|
325 | 323 | PdfFont font = getPropertyAsFont(Property.FONT);
|
326 |
| - if (!otfFeaturesApplied && script != null && isOtfFont(font)) { |
327 |
| - TypographyUtils.applyOtfScript(font.getFontProgram(), text, script); |
328 |
| - } |
| 324 | + if (!otfFeaturesApplied) { |
| 325 | + if (script == null && TypographyUtils.isTypographyModuleInitialized()) { |
| 326 | + // Try to autodetect complex script. |
| 327 | + Collection<Character.UnicodeScript> supportedScripts = TypographyUtils.getSupportedScripts(); |
| 328 | + if (supportedScripts != null) { |
| 329 | + Map<Character.UnicodeScript, Integer> scriptFrequency = new EnumMap<>(Character.UnicodeScript.class); |
| 330 | + for (int i = text.start; i < text.end; i++) { |
| 331 | + Integer unicode = text.get(i).getUnicode(); |
| 332 | + Character.UnicodeScript glyphScript = unicode != null ? Character.UnicodeScript.of(unicode) : null; |
| 333 | + if (glyphScript != null && supportedScripts.contains(glyphScript)) { |
| 334 | + if (scriptFrequency.containsKey(glyphScript)) { |
| 335 | + scriptFrequency.put(glyphScript, scriptFrequency.get(glyphScript)); |
| 336 | + } else { |
| 337 | + scriptFrequency.put(glyphScript, 1); |
| 338 | + } |
| 339 | + } |
| 340 | + } |
| 341 | + int max = 0; |
| 342 | + Character.UnicodeScript selectScript = null; |
| 343 | + for (Map.Entry<Character.UnicodeScript, Integer> entry : scriptFrequency.entrySet()) { |
| 344 | + if (entry.getValue() > max) { |
| 345 | + max = entry.getValue(); |
| 346 | + selectScript = entry.getKey(); |
| 347 | + } |
| 348 | + } |
| 349 | + if (selectScript != null) { |
| 350 | + script = selectScript; |
| 351 | + } |
| 352 | + } |
| 353 | + } |
| 354 | + |
| 355 | + if (isOtfFont(font) && script != null) { |
| 356 | + TypographyUtils.applyOtfScript(font.getFontProgram(), text, script); |
| 357 | + } |
329 | 358 |
|
330 |
| - if (!otfFeaturesApplied && fontKerning == Property.FontKerning.YES) { |
331 |
| - TypographyUtils.applyKerning(font.getFontProgram(), text); |
| 359 | + if (fontKerning == Property.FontKerning.YES) { |
| 360 | + TypographyUtils.applyKerning(font.getFontProgram(), text); |
| 361 | + } |
| 362 | + |
| 363 | + otfFeaturesApplied = true; |
332 | 364 | }
|
333 |
| - otfFeaturesApplied = true; |
334 | 365 | }
|
335 | 366 |
|
336 | 367 | @Override
|
@@ -647,16 +678,6 @@ public TextRenderer getNextRenderer() {
|
647 | 678 | return new TextRenderer((Text) modelElement, null);
|
648 | 679 | }
|
649 | 680 |
|
650 |
| - private static boolean checkTypographyModulePresence() { |
651 |
| - boolean moduleFound = false; |
652 |
| - try { |
653 |
| - Class.forName("com.itextpdf.typography.shaping.Shaper"); |
654 |
| - moduleFound = true; |
655 |
| - } catch (ClassNotFoundException ignored) { |
656 |
| - } |
657 |
| - return moduleFound; |
658 |
| - } |
659 |
| - |
660 | 681 | private boolean isNewLine(GlyphLine text, int ind) {
|
661 | 682 | return text.glyphs.get(ind).getUnicode() != null && text.glyphs.get(ind).getUnicode() == '\n';
|
662 | 683 | }
|
|
0 commit comments