|
40 | 40 | import org.openpdf.text.pdf.PdfString; |
41 | 41 |
|
42 | 42 | /** |
43 | | - * Renders a single PDF page to a {@link Graphics2D} surface, parsing the page's |
44 | | - * content stream with {@code openpdf-core}'s {@link PdfContentParser} and |
45 | | - * dispatching the resulting operators to Java2D drawing calls. |
| 43 | + * Renders a single PDF page to a {@link Graphics2D} surface, parsing the page's content stream with |
| 44 | + * {@code openpdf-core}'s {@link PdfContentParser} and dispatching the resulting operators to Java2D drawing calls. |
46 | 45 | * |
47 | 46 | * <p>This is the {@code openpdf-core}-driven Java2D rasterizer that backs |
48 | 47 | * {@link OpenPdfCoreRenderer#renderPage(int, float)}.</p> |
@@ -79,7 +78,9 @@ final class OpenPdfCorePageRenderer { |
79 | 78 |
|
80 | 79 | private static final Logger LOG = Logger.getLogger(OpenPdfCorePageRenderer.class.getName()); |
81 | 80 |
|
82 | | - /** Default user-space resolution of a PDF, in DPI. */ |
| 81 | + /** |
| 82 | + * Default user-space resolution of a PDF, in DPI. |
| 83 | + */ |
83 | 84 | private static final float PDF_USER_SPACE_DPI = 72f; |
84 | 85 |
|
85 | 86 | private final Graphics2D g2; |
@@ -115,8 +116,7 @@ private OpenPdfCorePageRenderer(Graphics2D g2, PdfDictionary resources) { |
115 | 116 | } |
116 | 117 |
|
117 | 118 | /** |
118 | | - * Renders the given page to {@code g2}, sized to {@code targetWidth x targetHeight} |
119 | | - * pixels at the requested DPI. |
| 119 | + * Renders the given page to {@code g2}, sized to {@code targetWidth x targetHeight} pixels at the requested DPI. |
120 | 120 | * |
121 | 121 | * @param reader the open PDF |
122 | 122 | * @param pageNumber 1-based page number |
@@ -198,8 +198,10 @@ private void processContent(byte[] contentBytes) throws IOException { |
198 | 198 | } |
199 | 199 | } |
200 | 200 |
|
201 | | - /** Dispatches one operator. Operands include the trailing operator literal at index size-1. */ |
202 | | - private void dispatch(String op, List<PdfObject> operands) throws IOException { |
| 201 | + /** |
| 202 | + * Dispatches one operator. Operands include the trailing operator literal at index size-1. |
| 203 | + */ |
| 204 | + private void dispatch(String op, List<PdfObject> operands) { |
203 | 205 | switch (op) { |
204 | 206 | // --- Graphics state --- |
205 | 207 | case "q": |
@@ -303,8 +305,7 @@ private void dispatch(String op, List<PdfObject> operands) throws IOException { |
303 | 305 | strokePath(); |
304 | 306 | resetPath(); |
305 | 307 | break; |
306 | | - case "f": |
307 | | - case "F": |
| 308 | + case "f", "F": |
308 | 309 | fillPath(Path2D.WIND_NON_ZERO); |
309 | 310 | resetPath(); |
310 | 311 | break; |
@@ -530,23 +531,33 @@ private Font mapFont(CMapAwareDocumentFont docFont, float size) { |
530 | 531 | String name = docFont.getPostscriptFontName(); |
531 | 532 | if (name != null) { |
532 | 533 | String lower = name.toLowerCase(); |
533 | | - if (lower.contains("mono") || lower.contains("courier")) { |
534 | | - family = Font.MONOSPACED; |
535 | | - } else if (lower.contains("sans") || lower.contains("helvetica") |
536 | | - || lower.contains("arial")) { |
537 | | - family = Font.SANS_SERIF; |
538 | | - } |
539 | | - if (lower.contains("bold")) { |
540 | | - style |= Font.BOLD; |
541 | | - } |
542 | | - if (lower.contains("italic") || lower.contains("oblique")) { |
543 | | - style |= Font.ITALIC; |
544 | | - } |
| 534 | + family = detectFontFamily(lower, family); |
| 535 | + style = detectStyles(lower, style); |
545 | 536 | } |
546 | 537 | } |
547 | 538 | return new Font(family, style, 1).deriveFont(Math.max(size, 0.1f)); |
548 | 539 | } |
549 | 540 |
|
| 541 | + private static int detectStyles(String lower, int style) { |
| 542 | + if (lower.contains("bold")) { |
| 543 | + style |= Font.BOLD; |
| 544 | + } |
| 545 | + if (lower.contains("italic") || lower.contains("oblique")) { |
| 546 | + style |= Font.ITALIC; |
| 547 | + } |
| 548 | + return style; |
| 549 | + } |
| 550 | + |
| 551 | + private static String detectFontFamily(String lower, String family) { |
| 552 | + if (lower.contains("mono") || lower.contains("courier")) { |
| 553 | + family = Font.MONOSPACED; |
| 554 | + } else if (lower.contains("sans") || lower.contains("helvetica") |
| 555 | + || lower.contains("arial")) { |
| 556 | + family = Font.SANS_SERIF; |
| 557 | + } |
| 558 | + return family; |
| 559 | + } |
| 560 | + |
550 | 561 | private CMapAwareDocumentFont lookupFont(String name) { |
551 | 562 | if (resources == null) { |
552 | 563 | return null; |
@@ -597,8 +608,11 @@ private static float clamp01(float v) { |
597 | 608 | return v; |
598 | 609 | } |
599 | 610 |
|
600 | | - /** Mutable per-graphics-state snapshot. Not thread-safe. */ |
| 611 | + /** |
| 612 | + * Mutable per-graphics-state snapshot. Not thread-safe. |
| 613 | + */ |
601 | 614 | private static final class GState { |
| 615 | + |
602 | 616 | Color fillColor = Color.BLACK; |
603 | 617 | Color strokeColor = Color.BLACK; |
604 | 618 | float lineWidth = 1.0f; |
|
0 commit comments