aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorSimon Steiner <ssteiner@apache.org>2023-07-20 12:52:09 +0100
committerSimon Steiner <ssteiner@apache.org>2023-07-20 12:52:09 +0100
commit05f8a2c9d2084b29b7ddf49a25d6a8e028243b7c (patch)
tree66a428bd3ea890a051e98a197f000e8cbe284a84
parentb16022ece329197f72f47943085d45b56e26806e (diff)
downloadxmlgraphics-fop-05f8a2c9d2084b29b7ddf49a25d6a8e028243b7c.tar.gz
xmlgraphics-fop-05f8a2c9d2084b29b7ddf49a25d6a8e028243b7c.zip
FOP-2985: Reset character spacing by Dave Roxburgh
-rw-r--r--fop-core/src/main/java/org/apache/fop/afp/ptoca/PtocaBuilder.java20
-rw-r--r--fop-core/src/main/java/org/apache/fop/render/afp/AFPPainter.java1
-rw-r--r--fop-core/src/main/java/org/apache/fop/render/pdf/PDFContentGenerator.java9
-rw-r--r--fop-core/src/main/java/org/apache/fop/render/pdf/PDFPainter.java2
-rw-r--r--fop-core/src/test/java/org/apache/fop/render/afp/AFPPainterTestCase.java46
-rw-r--r--fop-core/src/test/java/org/apache/fop/render/pdf/PDFPainterTestCase.java26
6 files changed, 95 insertions, 9 deletions
diff --git a/fop-core/src/main/java/org/apache/fop/afp/ptoca/PtocaBuilder.java b/fop-core/src/main/java/org/apache/fop/afp/ptoca/PtocaBuilder.java
index 084ba5daa..63026ee84 100644
--- a/fop-core/src/main/java/org/apache/fop/afp/ptoca/PtocaBuilder.java
+++ b/fop-core/src/main/java/org/apache/fop/afp/ptoca/PtocaBuilder.java
@@ -361,6 +361,26 @@ public abstract class PtocaBuilder implements PtocaConstants {
}
/**
+ * Resets the intercharacter adjustment (additional increment or decrement between graphic
+ * characters) to 0.
+ * <p>
+ * This is a modal control sequence.
+ *
+ * @throws IOException if an I/O error occurs
+ */
+ public void resetInterCharacterAdjustment() throws IOException {
+ if (0 == this.currentInterCharacterAdjustment) {
+ return;
+ }
+ newControlSequence();
+ writeShort(0); //Increment
+ writeBytes(0); // Direction
+ commit(chained(SIA));
+
+ this.currentInterCharacterAdjustment = 0;
+ }
+
+ /**
* A control sequence is a sequence of bytes that specifies a control
* function. A control sequence consists of a control sequence introducer
* and zero or more parameters. The control sequence can extend multiple
diff --git a/fop-core/src/main/java/org/apache/fop/render/afp/AFPPainter.java b/fop-core/src/main/java/org/apache/fop/render/afp/AFPPainter.java
index 9a4a7b93e..66ada9fac 100644
--- a/fop-core/src/main/java/org/apache/fop/render/afp/AFPPainter.java
+++ b/fop-core/src/main/java/org/apache/fop/render/afp/AFPPainter.java
@@ -1102,6 +1102,7 @@ public class AFPPainter extends AbstractIFPainter<AFPDocumentHandler> {
}
}
}
+ builder.resetInterCharacterAdjustment();
flushText(builder, sb, charSet);
if (pto != null) {
bytesAvailable = pto.getBytesAvailable();
diff --git a/fop-core/src/main/java/org/apache/fop/render/pdf/PDFContentGenerator.java b/fop-core/src/main/java/org/apache/fop/render/pdf/PDFContentGenerator.java
index 668734bde..0896ae8c3 100644
--- a/fop-core/src/main/java/org/apache/fop/render/pdf/PDFContentGenerator.java
+++ b/fop-core/src/main/java/org/apache/fop/render/pdf/PDFContentGenerator.java
@@ -424,6 +424,15 @@ public class PDFContentGenerator {
}
/**
+ * Resets the current character spacing (Tc) value to zero.
+ */
+ public void resetCharacterSpacing() {
+ if (getState().setCharacterSpacing(0)) {
+ getStream().add(format(0) + " Tc\n");
+ }
+ }
+
+ /**
* Establishes a new foreground or fill color.
* @param col the color to apply
* @param fill true to set the fill color, false for the foreground color
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 fc137c330..cebd083a8 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
@@ -526,6 +526,7 @@ public class PDFPainter extends AbstractIFPainter<PDFDocumentHandler> {
}
textutil.writeTJ();
+ generator.resetCharacterSpacing();
endSimulateStyle(tf, triplet);
}
@@ -599,6 +600,7 @@ public class PDFPainter extends AbstractIFPainter<PDFDocumentHandler> {
xoLast = xo;
yoLast = yo;
}
+ generator.resetCharacterSpacing();
endSimulateStyle(tf, triplet);
}
}
diff --git a/fop-core/src/test/java/org/apache/fop/render/afp/AFPPainterTestCase.java b/fop-core/src/test/java/org/apache/fop/render/afp/AFPPainterTestCase.java
index 3add2a495..b396d6d67 100644
--- a/fop-core/src/test/java/org/apache/fop/render/afp/AFPPainterTestCase.java
+++ b/fop-core/src/test/java/org/apache/fop/render/afp/AFPPainterTestCase.java
@@ -28,7 +28,6 @@ import java.io.File;
import java.io.IOException;
import java.io.InputStream;
import java.net.URI;
-import java.net.URISyntaxException;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
@@ -45,6 +44,8 @@ import static org.mockito.Mockito.mock;
import static org.mockito.Mockito.verify;
import static org.mockito.Mockito.when;
+import org.apache.commons.io.IOUtils;
+
import org.apache.xmlgraphics.image.loader.Image;
import org.apache.xmlgraphics.image.loader.ImageException;
import org.apache.xmlgraphics.image.loader.ImageFlavor;
@@ -155,7 +156,7 @@ public class AFPPainterTestCase {
}
@Test
- public void testPresentationText() throws URISyntaxException, IFException, IOException {
+ public void testPresentationText() throws Exception {
List<String> strings = new ArrayList<String>();
strings.add("test");
Assert.assertEquals(writeText(strings), "BEGIN DOCUMENT DOC00001\n"
@@ -190,7 +191,7 @@ public class AFPPainterTestCase {
}
@Test
- public void testPresentationText2() throws URISyntaxException, IFException, IOException {
+ public void testPresentationText2() throws Exception {
List<String> strings = new ArrayList<String>();
for (int i = 0; i < 5000; i++) {
strings.add("tes");
@@ -211,7 +212,37 @@ public class AFPPainterTestCase {
+ "END DOCUMENT DOC00001\n");
}
- private String writeText(List<String> text) throws URISyntaxException, IOException, IFException {
+ /**
+ * Checks that letter spacing is reset to 0 after the relevant text block.
+ */
+ @Test
+ public void testLetterSpacingReset() throws Exception {
+ List<String> strings = new ArrayList<>();
+ strings.add("xxxx");
+ InputStream inputStream = getDocResultInputStream(strings, 10000);
+ byte[] bytes = IOUtils.toByteArray(inputStream);
+ // The 134th byte is incremented by 5 to account for the 5 extra bytes inserted for the reset.
+ Assert.assertEquals((byte)39, bytes[134]);
+ // And these are the 5 reset bytes.
+ Assert.assertEquals((byte)5, bytes[163]);
+ Assert.assertEquals((byte)195, bytes[164]);
+ Assert.assertEquals((byte)0, bytes[165]);
+ Assert.assertEquals((byte)0, bytes[166]);
+ Assert.assertEquals((byte)0, bytes[167]);
+ }
+
+ private String writeText(List<String> text) throws Exception {
+ InputStream bis = getDocResultInputStream(text);
+ StringBuilder sb = new StringBuilder();
+ new AFPParser(false).read(bis, sb);
+ return sb.toString();
+ }
+
+ private static InputStream getDocResultInputStream(List<String> text) throws Exception {
+ return getDocResultInputStream(text, 0);
+ }
+
+ private static InputStream getDocResultInputStream(List<String> text, int letterSpacing) throws Exception {
FOUserAgent agent = FopFactory.newInstance(new URI(".")).newFOUserAgent();
IFContext context = new IFContext(agent);
AFPDocumentHandler doc = new AFPDocumentHandler(context);
@@ -232,14 +263,11 @@ public class AFPPainterTestCase {
doc.startDocument();
doc.startPage(0, "", "", new Dimension());
for (String s : text) {
- afpPainter.drawText(0, 0, 0, 0, null, s);
+ afpPainter.drawText(0, 0, letterSpacing, 0, null, s);
}
doc.endDocument();
- InputStream bis = new ByteArrayInputStream(outputStream.toByteArray());
- StringBuilder sb = new StringBuilder();
- new AFPParser(false).read(bis, sb);
- return sb.toString();
+ return new ByteArrayInputStream(outputStream.toByteArray());
}
@Test
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 7b5d34bdc..c2d9a325b 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
@@ -184,6 +184,32 @@ public class PDFPainterTestCase {
verify(pdfContentGenerator).add("0 Tr\n");
}
+ /**
+ * Tests that letter spacing is set and reset appropriately.
+ * @throws IFException
+ */
+ @Test
+ public void testLetterSpacing() throws IFException {
+ final StringBuilder sb = new StringBuilder();
+ pdfDocumentHandler = makePDFDocumentHandler(sb);
+
+ FontInfo fi = new FontInfo();
+ fi.addFontProperties("f1", new FontTriplet("a", "normal", 400));
+ MultiByteFont font = new MultiByteFont(null, null);
+ fi.addMetrics("f1", font);
+ pdfDocumentHandler.setFontInfo(fi);
+ MyPDFPainter pdfPainter = new MyPDFPainter(pdfDocumentHandler, null);
+ pdfPainter.setFont("a", "normal", 400, null, 12, null);
+ pdfPainter.drawText(0, 0, 4321, 0, null, "test");
+
+ assertEquals("BT\n"
+ + "/f1 0.012 Tf\n"
+ + "1 0 0 -1 0 0 Tm [<0000000000000000>] TJ\n",
+ sb.toString());
+ verify(pdfContentGenerator).updateCharacterSpacing(4.321f);
+ verify(pdfContentGenerator).resetCharacterSpacing();
+ }
+
@Test
public void testSimulateStyleColor() throws Exception {
FopFactory fopFactory = FopFactory.newInstance(new File(".").toURI());