diff --git a/openpdf/src/main/java/com/lowagie/text/html/FontSize.java b/openpdf/src/main/java/com/lowagie/text/html/FontSize.java new file mode 100644 index 000000000..b6ddad93b --- /dev/null +++ b/openpdf/src/main/java/com/lowagie/text/html/FontSize.java @@ -0,0 +1,57 @@ +package com.lowagie.text.html; + +/** + * Named font sizes defined by CSS + * font-size property + */ +public enum FontSize { + + // Absolute-size keywords, based on the user's default font size (which is medium). + XX_SMALL("xx-small", 0.6f, false), + X_SMALL("x-small", 0.75f, false), + SMALL("small", 0.89f, false), + MEDIUM("medium", 1.0f, false), + LARGE("large", 1.2f, false), + X_LARGE("x-large", 1.5f, false), + XX_LARGE("xx-large", 2.0f, false), + XXX_LARGE("xxx-large", 2.5f, false), + + // Relative-size keywords. The font will be larger or smaller relative to the parent element's font size, + // roughly by the ratio used to separate the absolute-size keywords above. + SMALLER("smaller", 0.89f, true), + LARGER("larger", 1.2f, true); + + private final float scale; + private final String textValue; + private final boolean relative; + + FontSize(String textValue, float scale, boolean relative) { + this.textValue = textValue; + this.scale = scale; + this.relative = relative; + } + + public String getTextValue() { + return textValue; + } + + public float getScale() { + return scale; + } + + public boolean isRelative() { + return relative; + } + + public static FontSize parse(String text) { + if (text == null || text.isEmpty() || !Character.isLetter(text.charAt(0))) { + return null; + } + for (FontSize fontSize : values()) { + if (fontSize.getTextValue().equalsIgnoreCase(text)) { + return fontSize; + } + } + return null; + } +} diff --git a/openpdf/src/main/java/com/lowagie/text/html/Markup.java b/openpdf/src/main/java/com/lowagie/text/html/Markup.java index c36f3187e..5c2b4a82a 100644 --- a/openpdf/src/main/java/com/lowagie/text/html/Markup.java +++ b/openpdf/src/main/java/com/lowagie/text/html/Markup.java @@ -479,6 +479,15 @@ public static float parseLength(String string, float actualFontSize) { if (string == null) { return 0f; } + FontSize fs = FontSize.parse(string);// it can be one of the CCS font size names (e.g. 'x-large') + if (fs != null) { + if (fs.isRelative()) { + return fs.getScale() * actualFontSize; + } else { + return fs.getScale() * DEFAULT_FONT_SIZE; + } + } + int pos = 0; int length = string.length(); boolean ok = true; diff --git a/openpdf/src/test/java/com/lowagie/text/html/FontSizeTest.java b/openpdf/src/test/java/com/lowagie/text/html/FontSizeTest.java index 86d3f151a..e645bfc06 100644 --- a/openpdf/src/test/java/com/lowagie/text/html/FontSizeTest.java +++ b/openpdf/src/test/java/com/lowagie/text/html/FontSizeTest.java @@ -11,6 +11,7 @@ import com.lowagie.text.pdf.PdfWriter; import java.io.StringReader; import java.nio.file.Files; +import java.nio.file.Path; import java.nio.file.Paths; import java.util.HashMap; import java.util.List; @@ -52,4 +53,62 @@ void testFontSize() throws Exception { Chunk chunk5 = (Chunk) paragraph.get(4); Assertions.assertEquals(0.5 * defaultFontSize, chunk5.getFont().getSize()); } + + @Test + void testNamedFontSize() throws Exception { + StringReader reader = new StringReader( + "" + + "Text xx-small
" + + "Text x-small
" + + "Text small
" + + "Text medium
" + + "Text large
" + + "Text x-large
" + + "Text xx-large
" + + "Text xxx-large
" + + "
" + + + "" + + "Text smaller
" + + "Text larger
" + + "
" + ); + StyleSheet styleSheet = new StyleSheet(); + Map interfaceProps = new HashMap<>(); + List elements = HTMLWorker.parseToList(reader, styleSheet, interfaceProps); + + Document document = new Document(); + PdfWriter instance = PdfWriter.getInstance(document, + Files.newOutputStream(Path.of("target/Font Size Named.pdf"))); + document.open(); + instance.getInfo().put(PdfName.CREATOR, new PdfString(Document.getVersion())); + for (Element e : elements) { + document.add(e); + } + document.close(); + + int i = 0; + Paragraph paragraph = (Paragraph) elements.get(0); + Chunk chunk1 = (Chunk) paragraph.get((i++) * 2); + Assertions.assertEquals(FontSize.XX_SMALL.getScale() * Markup.DEFAULT_FONT_SIZE, chunk1.getFont().getSize()); + Chunk chunk2 = (Chunk) paragraph.get((i++) * 2); + Assertions.assertEquals(FontSize.X_SMALL.getScale() * Markup.DEFAULT_FONT_SIZE, chunk2.getFont().getSize()); + Chunk chunk3 = (Chunk) paragraph.get((i++) * 2); + Assertions.assertEquals(FontSize.SMALL.getScale() * Markup.DEFAULT_FONT_SIZE, chunk3.getFont().getSize()); + Chunk chunk4 = (Chunk) paragraph.get((i++) * 2); + Assertions.assertEquals(FontSize.MEDIUM.getScale() * Markup.DEFAULT_FONT_SIZE, chunk4.getFont().getSize()); + Chunk chunk5 = (Chunk) paragraph.get((i++) * 2); + Assertions.assertEquals(FontSize.LARGE.getScale() * Markup.DEFAULT_FONT_SIZE, chunk5.getFont().getSize()); + Chunk chunk6 = (Chunk) paragraph.get((i++) * 2); + Assertions.assertEquals(FontSize.X_LARGE.getScale() * Markup.DEFAULT_FONT_SIZE, chunk6.getFont().getSize()); + Chunk chunk7 = (Chunk) paragraph.get((i++) * 2); + Assertions.assertEquals(FontSize.XX_LARGE.getScale() * Markup.DEFAULT_FONT_SIZE, chunk7.getFont().getSize()); + Chunk chunk8 = (Chunk) paragraph.get((i++) * 2); + Assertions.assertEquals(FontSize.XXX_LARGE.getScale() * Markup.DEFAULT_FONT_SIZE, chunk8.getFont().getSize()); + + Chunk chunk9 = (Chunk) paragraph.get((i++) * 2); + Assertions.assertEquals(FontSize.SMALLER.getScale() * 20f, chunk9.getFont().getSize()); + Chunk chunk10 = (Chunk) paragraph.get((i++) * 2); + Assertions.assertEquals(FontSize.LARGER.getScale() * 20f, chunk10.getFont().getSize()); + } }