diff options
author | Simon Steiner <ssteiner@apache.org> | 2022-04-21 13:48:07 +0000 |
---|---|---|
committer | Simon Steiner <ssteiner@apache.org> | 2022-04-21 13:48:07 +0000 |
commit | c2922dc45884758f516eca126e669c6e98c491e2 (patch) | |
tree | 6471307e0cc77730c1733e094494be98a8a995ca | |
parent | 1c35037f340df7ad112da5af646c878d2cf927c9 (diff) | |
download | xmlgraphics-fop-c2922dc45884758f516eca126e669c6e98c491e2.tar.gz xmlgraphics-fop-c2922dc45884758f516eca126e669c6e98c491e2.zip |
FOP-2977: Array index out of bounds with glyph position adjustments and surrogate pairs
git-svn-id: https://svn.apache.org/repos/asf/xmlgraphics/fop/trunk@1900111 13f79535-47bb-0310-9956-ffa450edef68
4 files changed, 43 insertions, 6 deletions
diff --git a/fop-core/src/main/java/org/apache/fop/fonts/GlyphMapping.java b/fop-core/src/main/java/org/apache/fop/fonts/GlyphMapping.java index dce045c2c..8eedafffa 100644 --- a/fop-core/src/main/java/org/apache/fop/fonts/GlyphMapping.java +++ b/fop-core/src/main/java/org/apache/fop/fonts/GlyphMapping.java @@ -157,7 +157,9 @@ public class GlyphMapping { // 6. compute word ipd based on final position adjustments. MinOptMax ipd = MinOptMax.ZERO; - for (int i = 0, n = mcs.length(); i < n; i++) { + + // The gpa array is sized by code point count + for (int i = 0, cpi = 0, n = mcs.length(); i < n; i++, cpi++) { int c = mcs.charAt(i); if (CharUtilities.containsSurrogatePairAt(mcs, i)) { @@ -169,7 +171,7 @@ public class GlyphMapping { w = 0; } if (gpa != null) { - w += gpa[i][GlyphPositioningTable.Value.IDX_X_ADVANCE]; + w += gpa[cpi][GlyphPositioningTable.Value.IDX_X_ADVANCE]; } ipd = ipd.plus(w); } diff --git a/fop-core/src/main/java/org/apache/fop/pdf/PDFTextUtil.java b/fop-core/src/main/java/org/apache/fop/pdf/PDFTextUtil.java index 552864d96..6ebdfd9b6 100644 --- a/fop-core/src/main/java/org/apache/fop/pdf/PDFTextUtil.java +++ b/fop-core/src/main/java/org/apache/fop/pdf/PDFTextUtil.java @@ -348,7 +348,7 @@ public abstract class PDFTextUtil { * Writes a "Tj" command with specified character code. * @param ch character code to write */ - public void writeTj(char ch, boolean multibyte, boolean cid) { + public void writeTj(int ch, boolean multibyte, boolean cid) { StringBuffer sb = new StringBuffer(); sb.append(startText); writeChar(ch, sb, multibyte, cid); diff --git a/fop-core/src/main/java/org/apache/fop/render/pdf/PDFPainter.java b/fop-core/src/main/java/org/apache/fop/render/pdf/PDFPainter.java index bf5f67894..fc137c330 100644 --- a/fop-core/src/main/java/org/apache/fop/render/pdf/PDFPainter.java +++ b/fop-core/src/main/java/org/apache/fop/render/pdf/PDFPainter.java @@ -577,7 +577,14 @@ public class PDFPainter extends AbstractIFPainter<PDFDocumentHandler> { tu.updateTf(fk, fsPoints, tf.isMultiByte(), true); generator.updateCharacterSpacing(letterSpacing / 1000f); for (int i = 0, n = text.length(); i < n; i++) { - char ch = text.charAt(i); + int ch = text.charAt(i); + int mp; + if (CharUtilities.containsSurrogatePairAt(text, i)) { + ch = Character.toCodePoint((char) ch, text.charAt(++i)); + mp = f.mapCodePoint(ch); + } else { + mp = f.mapChar((char)ch); + } int[] pa = ((i >= dp.length) || (dp[i] == null)) ? paZero : dp[i]; double xo = xc + pa[0]; double yo = yc + pa[1]; @@ -586,7 +593,7 @@ public class PDFPainter extends AbstractIFPainter<PDFDocumentHandler> { double xd = (xo - xoLast) / 1000f; double yd = (yo - yoLast) / 1000f; tu.writeTd(xd, yd); - tu.writeTj(f.mapChar(ch), tf.isMultiByte(), true); + tu.writeTj(mp, tf.isMultiByte(), true); xc += xa + pa[2]; yc += ya + pa[3]; xoLast = xo; @@ -596,7 +603,7 @@ public class PDFPainter extends AbstractIFPainter<PDFDocumentHandler> { } } - private double maybeWordOffsetX(double wox, char ch, Direction dir) { + private double maybeWordOffsetX(double wox, int ch, Direction dir) { if ((wox != 0) && CharUtilities.isAdjustableSpace(ch) && ((dir == null) || dir.isHorizontal())) { diff --git a/fop-core/src/test/java/org/apache/fop/render/pdf/PDFPainterTestCase.java b/fop-core/src/test/java/org/apache/fop/render/pdf/PDFPainterTestCase.java index 9fe1972a1..41747c72d 100644 --- a/fop-core/src/test/java/org/apache/fop/render/pdf/PDFPainterTestCase.java +++ b/fop-core/src/test/java/org/apache/fop/render/pdf/PDFPainterTestCase.java @@ -54,6 +54,7 @@ import org.apache.fop.apps.FopFactory; import org.apache.fop.events.Event; import org.apache.fop.events.EventListener; import org.apache.fop.fo.Constants; +import org.apache.fop.fonts.CMapSegment; import org.apache.fop.fonts.FontInfo; import org.apache.fop.fonts.FontTriplet; import org.apache.fop.fonts.MultiByteFont; @@ -243,6 +244,33 @@ public class PDFPainterTestCase { assertEquals("BT\n/f1 0.012 Tf\n1 0 0 -1 0 0 Tm [<" + expectedHex + ">] TJ\n", output.toString()); } + @Test + public void testDrawDpTextWithMultiByteFont() throws IFException { + StringBuilder output = new StringBuilder(); + PDFDocumentHandler pdfDocumentHandler = makePDFDocumentHandler(output); + String text = "Hi\uD83D\uDCA9"; + MultiByteFont font = new MultiByteFont(null, null); + font.setWidthArray(new int[10]); + font.setCMap(new CMapSegment[]{new CMapSegment(128169, 128169, 1)}); + FontInfo fi = new FontInfo(); + fi.addFontProperties("f1", new FontTriplet("a", "normal", 400)); + fi.addMetrics("f1", font); + pdfDocumentHandler.setFontInfo(fi); + MyPDFPainter pdfPainter = new MyPDFPainter(pdfDocumentHandler, null); + pdfPainter.setFont("a", "normal", 400, null, 12, null); + int[][] dp = new int[1][0]; + dp[0] = new int[]{0, 1, 2, 3}; + pdfPainter.drawText(0, 0, 0, 0, dp, text); + assertEquals("BT\n" + + "1 0 0 -1 0 0 Tm /f1 0.012 Tf\n" + + "0 0.001 Td\n" + + "<0000> Tj\n" + + "0.002 0.002 Td\n" + + "<0000> Tj\n" + + "0 0 Td\n" + + "<0001> Tj\n", output.toString()); + } + private PDFDocumentHandler makePDFDocumentHandler(final StringBuilder sb) throws IFException { FopFactory fopFactory = FopFactory.newInstance(new File(".").toURI()); foUserAgent = fopFactory.newFOUserAgent(); |