Skip to content

Commit d45b38e

Browse files
committed
Rework font selection strategies and add a new one (char by char) and add logic for diacritics
DEVSIX-2052
1 parent a57e642 commit d45b38e

21 files changed

+894
-40
lines changed

io/src/main/java/com/itextpdf/io/util/TextUtil.java

Lines changed: 13 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -38,6 +38,17 @@ public final class TextUtil {
3838
private TextUtil() {
3939
}
4040

41+
/**
42+
* Checks if the passed code point corresponds to diacritic.
43+
*
44+
* @param codePoint the code point to check
45+
*
46+
* @return {@code true} if passed code point is diacritic, {@code false} otherwise
47+
*/
48+
public static boolean isDiacritic(int codePoint) {
49+
return codePoint > 0x0300 && codePoint <= 0x036F;
50+
}
51+
4152
/**
4253
* Check if the value of a character belongs to a certain interval
4354
* that indicates it's the higher part of a surrogate pair.
@@ -71,7 +82,7 @@ public static char lowSurrogate(int codePoint) {
7182

7283
/**
7384
* Checks if two subsequent characters in a String are
74-
* are the higher and the lower character in a surrogate
85+
* the higher and the lower character in a surrogate
7586
* pair (and therefore eligible for conversion to a UTF 32 character).
7687
*
7788
* @param text the String with the high and low surrogate characters
@@ -86,7 +97,7 @@ && isSurrogateHigh(text.charAt(idx))
8697

8798
/**
8899
* Checks if two subsequent characters in a character array are
89-
* are the higher and the lower character in a surrogate
100+
* the higher and the lower character in a surrogate
90101
* pair (and therefore eligible for conversion to a UTF 32 character).
91102
*
92103
* @param text the character array with the high and low surrogate characters

io/src/test/java/com/itextpdf/io/util/TextUtilTest.java

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -112,6 +112,12 @@ public void isMarkNegativeTest() {
112112
Assert.assertFalse(TextUtil.isMark(glyph));
113113
}
114114

115+
@Test
116+
public void isDiacriticTest() {
117+
Assert.assertTrue(TextUtil.isDiacritic("\u0303".charAt(0)));
118+
Assert.assertFalse(TextUtil.isDiacritic("\u006b".charAt(0)));
119+
}
120+
115121
private void helper(boolean expected, int currentCRPosition, Glyph...glyphs) {
116122
GlyphLine glyphLine = new GlyphLine(Arrays.asList(glyphs));
117123
Assert.assertTrue(expected == TextUtil.isCarriageReturnFollowedByLineFeed(glyphLine, currentCRPosition));

layout/src/main/java/com/itextpdf/layout/font/ComplexFontSelectorStrategy.java

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -25,6 +25,7 @@ This file is part of the iText (R) project.
2525
import com.itextpdf.io.font.otf.Glyph;
2626
import com.itextpdf.io.util.TextUtil;
2727
import com.itextpdf.kernel.font.PdfFont;
28+
import com.itextpdf.layout.font.selectorstrategy.FirstMatchFontSelectorStrategy;
2829

2930
import java.util.ArrayList;
3031
import java.util.List;
@@ -33,7 +34,9 @@ This file is part of the iText (R) project.
3334
* Complex FontSelectorStrategy split text based on {@link java.lang.Character.UnicodeScript}.
3435
* If unicode script changes, a new font will be found.
3536
* If there is no suitable font, only one notdef glyph from {@link FontSelector#bestMatch()} will be added.
37+
* @deprecated was replaced by {@link FirstMatchFontSelectorStrategy}.
3638
*/
39+
@Deprecated
3740
public class ComplexFontSelectorStrategy extends FontSelectorStrategy {
3841

3942
private PdfFont font;

layout/src/main/java/com/itextpdf/layout/font/FontProvider.java

Lines changed: 45 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -22,19 +22,22 @@ This file is part of the iText (R) project.
2222
*/
2323
package com.itextpdf.layout.font;
2424

25+
import com.itextpdf.commons.utils.FileUtil;
2526
import com.itextpdf.io.font.FontCache;
2627
import com.itextpdf.io.font.FontProgram;
2728
import com.itextpdf.io.font.FontProgramFactory;
2829
import com.itextpdf.io.font.PdfEncodings;
2930
import com.itextpdf.io.font.Type1Font;
3031
import com.itextpdf.io.font.constants.StandardFonts;
31-
import com.itextpdf.commons.utils.FileUtil;
3232
import com.itextpdf.kernel.exceptions.PdfException;
3333
import com.itextpdf.kernel.font.PdfFont;
3434
import com.itextpdf.kernel.font.PdfFontFactory;
3535
import com.itextpdf.kernel.font.PdfFontFactory.EmbeddingStrategy;
3636
import com.itextpdf.kernel.pdf.PdfDocument;
3737
import com.itextpdf.layout.exceptions.LayoutExceptionMessageConstant;
38+
import com.itextpdf.layout.font.selectorstrategy.FirstMatchFontSelectorStrategy.FirstMathFontSelectorStrategyFactory;
39+
import com.itextpdf.layout.font.selectorstrategy.IFontSelectorStrategy;
40+
import com.itextpdf.layout.font.selectorstrategy.IFontSelectorStrategyFactory;
3841

3942
import java.io.IOException;
4043
import java.util.ArrayList;
@@ -53,7 +56,7 @@ This file is part of the iText (R) project.
5356
* <p>
5457
* It is allowed to use only one {@link FontProvider} per document. If additional fonts per element needed,
5558
* another instance of {@link FontSet} can be used. For more details see {@link com.itextpdf.layout.properties.Property#FONT_SET},
56-
* {@link #getPdfFont(FontInfo, FontSet)}, {@link #getStrategy(String, List, FontCharacteristics, FontSet)}.
59+
* {@link #getPdfFont(FontInfo, FontSet)}, {@link #createFontSelectorStrategy(List, FontCharacteristics, FontSet)}.
5760
* <p>
5861
* Note, FontProvider does not close created {@link FontProgram}s, because of possible conflicts with {@link FontCache}.
5962
*/
@@ -69,6 +72,8 @@ public class FontProvider {
6972
protected final String defaultFontFamily;
7073
protected final Map<FontInfo, PdfFont> pdfFonts;
7174

75+
private IFontSelectorStrategyFactory fontSelectorStrategyFactory;
76+
7277
/**
7378
* Creates a new instance of FontProvider.
7479
*
@@ -105,6 +110,7 @@ public FontProvider(FontSet fontSet, String defaultFontFamily) {
105110
pdfFonts = new HashMap<>();
106111
fontSelectorCache = new FontSelectorCache(this.fontSet);
107112
this.defaultFontFamily = defaultFontFamily;
113+
this.fontSelectorStrategyFactory = new FirstMathFontSelectorStrategyFactory();
108114
}
109115

110116
/**
@@ -364,7 +370,9 @@ public boolean getDefaultEmbeddingFlag() {
364370
* font selector strategy instance and will not be otherwise preserved in font provider.
365371
*
366372
* @return {@link FontSelectorStrategy} instance.
373+
* @deprecated use {@link #createFontSelectorStrategy(List, FontCharacteristics, FontSet)}
367374
*/
375+
@Deprecated
368376
public FontSelectorStrategy getStrategy(String text, List<String> fontFamilies, FontCharacteristics fc, FontSet additionalFonts) {
369377
return new ComplexFontSelectorStrategy(text, getFontSelector(fontFamilies, fc, additionalFonts), this, additionalFonts);
370378
}
@@ -379,7 +387,9 @@ public FontSelectorStrategy getStrategy(String text, List<String> fontFamilies,
379387
* @param fc instance of {@link FontCharacteristics} to create {@link FontSelector} for sequences of glyphs.
380388
*
381389
* @return {@link FontSelectorStrategy} instance.
390+
* @deprecated use {@link #createFontSelectorStrategy(List, FontCharacteristics, FontSet)}
382391
*/
392+
@Deprecated
383393
public FontSelectorStrategy getStrategy(String text, List<String> fontFamilies, FontCharacteristics fc) {
384394
return getStrategy(text, fontFamilies, fc, null);
385395
}
@@ -393,11 +403,44 @@ public FontSelectorStrategy getStrategy(String text, List<String> fontFamilies,
393403
* @param fontFamilies target font families to create {@link FontSelector} for sequences of glyphs.
394404
*
395405
* @return {@link FontSelectorStrategy} instance.
406+
* @deprecated use {@link #createFontSelectorStrategy(List, FontCharacteristics, FontSet)}
396407
*/
408+
@Deprecated
397409
public FontSelectorStrategy getStrategy(String text, List<String> fontFamilies) {
398410
return getStrategy(text, fontFamilies, null);
399411
}
400412

413+
/**
414+
* Sets factory which will be used in {@link #createFontSelectorStrategy(List, FontCharacteristics, FontSet)}
415+
* method.
416+
*
417+
* @param factory the factory which will be used to create font selector strategies
418+
*/
419+
public void setFontSelectorStrategyFactory(IFontSelectorStrategyFactory factory) {
420+
this.fontSelectorStrategyFactory = factory;
421+
}
422+
423+
/**
424+
* Creates the {@link IFontSelectorStrategy} to split text into sequences of glyphs, already tied
425+
* to the fonts which contain them. The fonts can be taken from the added fonts to the font provider and
426+
* are chosen based on font-families list and desired font characteristics.
427+
*
428+
* @param fontFamilies target font families to create {@link FontSelector} for sequences of glyphs.
429+
* @param fc instance of {@link FontCharacteristics} to create {@link FontSelector} for sequences of glyphs.
430+
* @param additionalFonts set which provides fonts additionally to the fonts added to font provider.
431+
* Combined set of font provider fonts and additional fonts is used when choosing
432+
* a single font for a sequence of glyphs. Additional fonts will only be used for the given
433+
* font selector strategy instance and will not be otherwise preserved in font provider.
434+
*
435+
* @return {@link IFontSelectorStrategy} instance
436+
*/
437+
public IFontSelectorStrategy createFontSelectorStrategy(List<String> fontFamilies,
438+
FontCharacteristics fc, FontSet additionalFonts) {
439+
440+
final FontSelector fontSelector = getFontSelector(fontFamilies, fc, additionalFonts);
441+
return fontSelectorStrategyFactory.createFontSelectorStrategy(this, fontSelector, additionalFonts);
442+
}
443+
401444
/**
402445
* Create {@link FontSelector} or get from cache.
403446
*

layout/src/main/java/com/itextpdf/layout/font/FontSelectorStrategy.java

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -24,13 +24,16 @@ This file is part of the iText (R) project.
2424

2525
import com.itextpdf.io.font.otf.Glyph;
2626
import com.itextpdf.kernel.font.PdfFont;
27+
import com.itextpdf.layout.font.selectorstrategy.IFontSelectorStrategy;
2728

2829
import java.util.List;
2930

3031
/**
3132
* {@link FontSelectorStrategy} is responsible for splitting text into sub texts with one particular font.
3233
* {@link #nextGlyphs()} will create next sub text and set current font.
34+
* @deprecated replaced by {@link IFontSelectorStrategy}.
3335
*/
36+
@Deprecated
3437
public abstract class FontSelectorStrategy {
3538

3639
protected String text;

0 commit comments

Comments
 (0)