|
3 | 3 | import static org.hamcrest.CoreMatchers.startsWith; |
4 | 4 | import static org.hamcrest.MatcherAssert.assertThat; |
5 | 5 | import static org.junit.Assert.assertEquals; |
| 6 | +import static org.junit.Assert.assertNotNull; |
6 | 7 |
|
7 | 8 | import java.io.IOException; |
8 | 9 | import java.util.Collections; |
@@ -114,13 +115,73 @@ public void testInvalidAppearanceString() throws IOException |
114 | 115 | helper.setAppearanceValue("Some text"); |
115 | 116 | } |
116 | 117 |
|
| 118 | + @Test |
| 119 | + public void testCalculateFontSizeWithNonPrintableChars() throws IOException |
| 120 | + { |
| 121 | + PDTextField field = multilineTextFieldFaux(); |
| 122 | + |
| 123 | + AppearanceGeneratorHelper helper = new AppearanceGeneratorHelper(field); |
| 124 | + helper.setAppearanceValue("This isnt multiple lines\r"); |
| 125 | + |
| 126 | + assertNotNull(field.getWidgets().get(0).getNormalAppearanceStream()); |
| 127 | + } |
| 128 | + |
| 129 | + @Test |
| 130 | + public void testCalculateFontSizeWithExoticWhiteSpace() throws IOException |
| 131 | + { |
| 132 | + PDTextField field = multilineTextFieldFaux(); |
| 133 | + |
| 134 | + AppearanceGeneratorHelper helper = new AppearanceGeneratorHelper(field); |
| 135 | + helper.setAppearanceValue("This is\u2002whitespace"); |
| 136 | + |
| 137 | + assertNotNull(field.getWidgets().get(0).getNormalAppearanceStream()); |
| 138 | + } |
| 139 | + |
| 140 | + @Test |
| 141 | + public void testComboBoxAppearanceWithExoticWhiteSpace() throws IOException |
| 142 | + { |
| 143 | + PDComboBox field = comboBox(); |
| 144 | + |
| 145 | + // U+2002 (en space) has no glyph in Helvetica / WinAnsiEncoding. Before it is |
| 146 | + // normalized to a regular space, generating the combo box appearance threw |
| 147 | + // IllegalArgumentException from PDFont.encode (reached via getStringWidth in |
| 148 | + // calculateFontSize, and via showText in the rendering path). |
| 149 | + // |
| 150 | + // setValue drives the exact path from the original crash report: |
| 151 | + // PDChoice.setValue -> applyChange -> constructAppearances -> setAppearanceValue |
| 152 | + field.setValue("Option\u2002One"); |
| 153 | + |
| 154 | + // appearance generation must complete and produce a stream, not silently skip |
| 155 | + assertNotNull(field.getWidgets().get(0).getNormalAppearanceStream()); |
| 156 | + } |
| 157 | + |
| 158 | + private PDComboBox comboBox() |
| 159 | + { |
| 160 | + PDDocument doc = new PDDocument(); |
| 161 | + doc.addPage(new PDPage()); |
| 162 | + PDAcroForm form = new PDAcroForm(doc); |
| 163 | + PDComboBox cb = new PDComboBox(form); |
| 164 | + cb.setDefaultAppearance("/Helvetica 10.00 Tf 0 g"); |
| 165 | + cb.getWidgets().get(0).setRectangle(new PDRectangle(2, 2, 100, 20)); |
| 166 | + return cb; |
| 167 | + } |
| 168 | + |
117 | 169 | private PDTextField multilineTextField() |
118 | 170 | { |
119 | 171 | PDTextField tf = textField(); |
120 | 172 | tf.setMultiline(true); |
121 | 173 | return tf; |
122 | 174 | } |
123 | 175 |
|
| 176 | + private PDTextField multilineTextFieldFaux() |
| 177 | + { |
| 178 | + PDTextField field = multilineTextField(); |
| 179 | + // faux multiline, content rectangle not tall enough |
| 180 | + field.getWidgets().get(0).setRectangle(new PDRectangle(2, 2, 517, 10)); |
| 181 | + field.setDefaultAppearance("Helvetica 0 Tf 0 g"); |
| 182 | + return field; |
| 183 | + } |
| 184 | + |
124 | 185 | private PDTextField textField() |
125 | 186 | { |
126 | 187 | PDDocument doc = new PDDocument(); |
|
0 commit comments