|
16 | 16 | import com.itextpdf.layout.Canvas; |
17 | 17 | import com.itextpdf.layout.Document; |
18 | 18 | import com.itextpdf.layout.borders.Border; |
| 19 | +import com.itextpdf.layout.element.AbstractElement; |
19 | 20 | import com.itextpdf.layout.element.Cell; |
20 | 21 | import com.itextpdf.layout.element.Div; |
21 | 22 | import com.itextpdf.layout.element.IBlockElement; |
|
26 | 27 | import com.itextpdf.layout.element.Paragraph; |
27 | 28 | import com.itextpdf.layout.element.Table; |
28 | 29 | import com.itextpdf.layout.element.Text; |
| 30 | +import com.itextpdf.layout.font.FontProvider; |
| 31 | +import com.itextpdf.layout.font.FontSet; |
29 | 32 | import com.itextpdf.layout.properties.HorizontalAlignment; |
| 33 | +import com.itextpdf.layout.properties.Property; |
30 | 34 | import com.itextpdf.layout.properties.TextAlignment; |
31 | 35 | import com.itextpdf.layout.properties.UnitValue; |
32 | 36 | import de.tum.cit.aet.core.exception.PDFGenerationException; |
@@ -59,6 +63,9 @@ public class PDFBuilder { |
59 | 63 | private static final DeviceRgb PRIMARY_COLOR = new DeviceRgb(0x18, 0x72, 0xDD); |
60 | 64 | private static final DeviceRgb METADATA_COLOR = new DeviceRgb(0x8d, 0x8d, 0x8f); |
61 | 65 |
|
| 66 | + // Reused across exports so converted HTML uses the same Helvetica font as the rest of the document. |
| 67 | + private static final FontProvider HTML_FONT_PROVIDER = createHelveticaFontProvider(); |
| 68 | + |
62 | 69 | // ----------------- Font Sizes ----------------- |
63 | 70 | private static final float FONT_SIZE_MAIN_HEADING = 18f; |
64 | 71 |
|
@@ -529,18 +536,52 @@ private void addMetadata(PdfDocument pdfDoc, PdfFont normalFont) { |
529 | 536 | } |
530 | 537 | } |
531 | 538 |
|
| 539 | + /** |
| 540 | + * Creates a font provider exposing only the Helvetica family (regular, bold, italic and |
| 541 | + * bold-italic) with Helvetica as the default family, so HTML conversion stays on a single font. |
| 542 | + * |
| 543 | + * @return a font provider limited to the Helvetica family |
| 544 | + */ |
| 545 | + private static FontProvider createHelveticaFontProvider() { |
| 546 | + FontSet fontSet = new FontSet(); |
| 547 | + fontSet.addFont(StandardFonts.HELVETICA); |
| 548 | + fontSet.addFont(StandardFonts.HELVETICA_BOLD); |
| 549 | + fontSet.addFont(StandardFonts.HELVETICA_OBLIQUE); |
| 550 | + fontSet.addFont(StandardFonts.HELVETICA_BOLDOBLIQUE); |
| 551 | + return new FontProvider(fontSet, StandardFonts.HELVETICA); |
| 552 | + } |
| 553 | + |
| 554 | + /** |
| 555 | + * Drops the font sizes the HTML converter resolved onto nested elements so that they inherit the |
| 556 | + * size set on the surrounding block instead. Converted bold and italic runs carry their own font |
| 557 | + * size, which would otherwise take precedence and render them larger than the text around them. |
| 558 | + * Their font is deliberately kept, since that is what selects the bold or italic Helvetica variant. |
| 559 | + * |
| 560 | + * @param element the converted element whose descendants should inherit the block font size |
| 561 | + */ |
| 562 | + private static void clearNestedFontSizes(IElement element) { |
| 563 | + if (element instanceof AbstractElement<?> abstractElement) { |
| 564 | + for (IElement child : abstractElement.getChildren()) { |
| 565 | + child.deleteOwnProperty(Property.FONT_SIZE); |
| 566 | + clearNestedFontSizes(child); |
| 567 | + } |
| 568 | + } |
| 569 | + } |
| 570 | + |
532 | 571 | private List<IBlockElement> parseHtmlContent(String html, PdfFont normalFont) { |
533 | 572 | List<IBlockElement> elements = new ArrayList<>(); |
534 | 573 |
|
535 | 574 | try { |
536 | 575 | String processedHtml = html.replaceAll("<ol>", "<ul>").replaceAll("</ol>", "</ul>"); |
537 | 576 |
|
538 | 577 | ConverterProperties props = new ConverterProperties(); |
| 578 | + props.setFontProvider(HTML_FONT_PROVIDER); |
539 | 579 |
|
540 | 580 | List<IElement> pdfElements = HtmlConverter.convertToElements(processedHtml, props); |
541 | 581 |
|
542 | 582 | for (IElement element : pdfElements) { |
543 | 583 | if (element instanceof IBlockElement blockElement) { |
| 584 | + clearNestedFontSizes(blockElement); |
544 | 585 | if (blockElement instanceof Paragraph) { |
545 | 586 | ((Paragraph) blockElement).setFont(normalFont) |
546 | 587 | .setFontSize(FONT_SIZE_TEXT) |
|
0 commit comments