aboutsummaryrefslogtreecommitdiffstats
path: root/fop-core/src
diff options
context:
space:
mode:
authorSimon Steiner <ssteiner@apache.org>2022-01-28 10:27:59 +0000
committerSimon Steiner <ssteiner@apache.org>2022-01-28 10:27:59 +0000
commit999ca17b4f4c879db6e40c58cca8763129bd4b07 (patch)
tree32eda3c25d7a04aaf06573acc1ed9b6218a015d2 /fop-core/src
parentfa96721ca8a7a8ed0d4de31e919c28921444c9d9 (diff)
downloadxmlgraphics-fop-999ca17b4f4c879db6e40c58cca8763129bd4b07.tar.gz
xmlgraphics-fop-999ca17b4f4c879db6e40c58cca8763129bd4b07.zip
FOP-3049: Align AFP SVG text in the middle
git-svn-id: https://svn.apache.org/repos/asf/xmlgraphics/fop/trunk@1897561 13f79535-47bb-0310-9956-ffa450edef68
Diffstat (limited to 'fop-core/src')
-rw-r--r--fop-core/src/main/java/org/apache/fop/image/loader/batik/BatikUtil.java10
-rw-r--r--fop-core/src/main/java/org/apache/fop/svg/AbstractFOPTextPainter.java10
-rw-r--r--fop-core/src/test/java/org/apache/fop/render/afp/AFPTrueTypeTestCase.java69
3 files changed, 72 insertions, 17 deletions
diff --git a/fop-core/src/main/java/org/apache/fop/image/loader/batik/BatikUtil.java b/fop-core/src/main/java/org/apache/fop/image/loader/batik/BatikUtil.java
index cda57b596..7162df971 100644
--- a/fop-core/src/main/java/org/apache/fop/image/loader/batik/BatikUtil.java
+++ b/fop-core/src/main/java/org/apache/fop/image/loader/batik/BatikUtil.java
@@ -19,8 +19,10 @@
package org.apache.fop.image.loader.batik;
+import org.w3c.dom.DOMImplementation;
import org.w3c.dom.Document;
+import org.apache.batik.anim.dom.SVGDOMImplementation;
import org.apache.batik.dom.AbstractDocument;
import org.apache.batik.dom.util.DOMUtilities;
@@ -53,9 +55,13 @@ public final class BatikUtil {
* @return the cloned SVG DOM
*/
public static Document cloneSVGDocument(Document doc) {
- Document clonedDoc = DOMUtilities.deepCloneDocument(doc, doc.getImplementation());
+ DOMImplementation impl = doc.getImplementation();
+ if (!(impl instanceof SVGDOMImplementation)) {
+ impl = new SVGDOMImplementation();
+ }
+ Document clonedDoc = DOMUtilities.deepCloneDocument(doc, impl);
if (clonedDoc instanceof AbstractDocument) {
- ((AbstractDocument)clonedDoc).setDocumentURI(((AbstractDocument)doc).getDocumentURI());
+ clonedDoc.setDocumentURI(doc.getDocumentURI());
}
return clonedDoc;
}
diff --git a/fop-core/src/main/java/org/apache/fop/svg/AbstractFOPTextPainter.java b/fop-core/src/main/java/org/apache/fop/svg/AbstractFOPTextPainter.java
index df24dbb92..30843121d 100644
--- a/fop-core/src/main/java/org/apache/fop/svg/AbstractFOPTextPainter.java
+++ b/fop-core/src/main/java/org/apache/fop/svg/AbstractFOPTextPainter.java
@@ -36,6 +36,7 @@ import org.apache.batik.bridge.Mark;
import org.apache.batik.bridge.StrokingTextPainter;
import org.apache.batik.bridge.TextNode;
import org.apache.batik.bridge.TextPainter;
+import org.apache.batik.gvt.font.GVTGlyphVector;
import org.apache.batik.gvt.text.GVTAttributedCharacterIterator;
import org.apache.batik.gvt.text.TextPaintInfo;
@@ -157,7 +158,14 @@ public abstract class AbstractFOPTextPainter implements TextPainter {
if (font != null) {
fontSize = (int) Math.round(afpg2d.convertToAbsoluteLength(font.getFontSize()));
}
- if (fontSize < 6000) {
+ if (anchor != null && TextNode.Anchor.ANCHOR_MIDDLE == anchor.getType()) {
+ GVTGlyphVector gv = run.getLayout().getGlyphVector();
+ Point2D glyphPos = gv.getGlyphPosition(0);
+ double advanceChar = afpg2d.convertToAbsoluteLength(advance / txt.length());
+ nativeTextHandler.drawString(g2d, txt,
+ (float) (currentLocation.getX() - advanceChar - glyphPos.getX()),
+ (float) (currentLocation.getY() + glyphPos.getY()));
+ } else if (fontSize < 6000) {
nativeTextHandler.drawString(g2d, txt, (float) (x + tx), (float) y);
} else {
double scaleX = g2d.getTransform().getScaleX();
diff --git a/fop-core/src/test/java/org/apache/fop/render/afp/AFPTrueTypeTestCase.java b/fop-core/src/test/java/org/apache/fop/render/afp/AFPTrueTypeTestCase.java
index 9a9e5bed7..f875d80d8 100644
--- a/fop-core/src/test/java/org/apache/fop/render/afp/AFPTrueTypeTestCase.java
+++ b/fop-core/src/test/java/org/apache/fop/render/afp/AFPTrueTypeTestCase.java
@@ -21,17 +21,16 @@ package org.apache.fop.render.afp;
import java.awt.Color;
import java.io.ByteArrayInputStream;
import java.io.ByteArrayOutputStream;
+import java.io.DataInputStream;
import java.io.File;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.net.URI;
-import java.net.URISyntaxException;
import javax.xml.transform.Result;
import javax.xml.transform.Source;
import javax.xml.transform.Transformer;
-import javax.xml.transform.TransformerException;
import javax.xml.transform.TransformerFactory;
import javax.xml.transform.sax.SAXResult;
import javax.xml.transform.stream.StreamSource;
@@ -39,8 +38,6 @@ import javax.xml.transform.stream.StreamSource;
import org.junit.Assert;
import org.junit.Test;
-import org.xml.sax.SAXException;
-
import static org.mockito.Mockito.mock;
import static org.mockito.Mockito.when;
@@ -53,6 +50,8 @@ import org.apache.fop.afp.DataStream;
import org.apache.fop.afp.Factory;
import org.apache.fop.afp.fonts.FopCharacterSet;
import org.apache.fop.afp.modca.PageObject;
+import org.apache.fop.afp.parser.MODCAParser;
+import org.apache.fop.afp.parser.UnparsedStructuredField;
import org.apache.fop.apps.EnvironmentalProfileFactory;
import org.apache.fop.apps.FOUserAgent;
import org.apache.fop.apps.Fop;
@@ -66,8 +65,6 @@ import org.apache.fop.fonts.FontTriplet;
import org.apache.fop.fonts.MultiByteFont;
import org.apache.fop.render.intermediate.IFException;
-
-
public class AFPTrueTypeTestCase {
private String font;
private String fopxconf = "<fop version=\"1.0\">\n"
@@ -90,7 +87,7 @@ public class AFPTrueTypeTestCase {
+ "</fop>";
@Test
- public void testAFPTrueType() throws IOException, SAXException, TransformerException, URISyntaxException {
+ public void testAFPTrueType() throws Exception {
String fo = "<fo:root xmlns:fo=\"http://www.w3.org/1999/XSL/Format\">\n"
+ " <fo:layout-master-set>\n"
+ " <fo:simple-page-master master-name=\"simple\">\n"
@@ -189,7 +186,7 @@ public class AFPTrueTypeTestCase {
}
@Test
- public void testSVGAFPTrueType() throws IOException, SAXException, TransformerException, URISyntaxException {
+ public void testSVGAFPTrueType() throws Exception {
String fo = "<fo:root xmlns:fo=\"http://www.w3.org/1999/XSL/Format\" "
+ "xmlns:fox=\"http://xmlgraphics.apache.org/fop/extensions\" "
+ "xmlns:svg=\"http://www.w3.org/2000/svg\">\n"
@@ -228,7 +225,55 @@ public class AFPTrueTypeTestCase {
Assert.assertTrue(getAFP(fo).contains("DATA GRAPHICS"));
}
- private String getAFP(String fo) throws IOException, TransformerException, SAXException, URISyntaxException {
+ @Test
+ public void testSVGAnchorAFP() throws Exception {
+ String fo = "<fo:root xmlns:fo=\"http://www.w3.org/1999/XSL/Format\" "
+ + "xmlns:svg=\"http://www.w3.org/2000/svg\">\n"
+ + " <fo:layout-master-set>\n"
+ + " <fo:simple-page-master master-name=\"simple\" page-height=\"27.9cm\" page-width=\"21.6cm\">\n"
+ + " <fo:region-body />\n"
+ + " </fo:simple-page-master>\n"
+ + " </fo:layout-master-set>\n"
+ + " <fo:page-sequence master-reference=\"simple\">\n"
+ + " <fo:flow flow-name=\"xsl-region-body\"> \n"
+ + " <fo:block font-size=\"0\">\n"
+ + " <fo:instream-foreign-object content-height=\"792pt\" content-width=\"612pt\">\n"
+ + "<svg:svg xmlns=\"http://www.w3.org/2000/svg\" height=\"3mm\" viewBox=\"0 0 49.94 3\" "
+ + "width=\"49.94mm\">\n"
+ + " <svg:g fill=\"black\" stroke=\"none\">\n"
+ + " <svg:text font-family=\"ExpertSans\" font-size=\"2.8219\" text-anchor=\"middle\" x=\"24.97\" "
+ + "y=\"2.6228\">0000210122010000000100010004</svg:text>\n"
+ + " </svg:g>\n"
+ + "</svg:svg>\n"
+ + " </fo:instream-foreign-object>\n"
+ + " </fo:block>\n"
+ + " </fo:flow>\n"
+ + " </fo:page-sequence>\n"
+ + "</fo:root>";
+ ByteArrayOutputStream bos = getAFPBytes(fo);
+ MODCAParser parser = new MODCAParser(new ByteArrayInputStream(bos.toByteArray()));
+ UnparsedStructuredField structuredField;
+ while ((structuredField = parser.readNextStructuredField()) != null) {
+ if (structuredField.toString().contains("Data Graphics")) {
+ break;
+ }
+ }
+ DataInputStream bis = new DataInputStream(new ByteArrayInputStream(structuredField.getData()));
+ bis.skip(34);
+ //X Y coordinates:
+ Assert.assertEquals(bis.readShort(), 3);
+ Assert.assertEquals(bis.readShort(), 5);
+ }
+
+ private String getAFP(String fo) throws Exception {
+ ByteArrayOutputStream bos = getAFPBytes(fo);
+ StringBuilder sb = new StringBuilder();
+ InputStream bis = new ByteArrayInputStream(bos.toByteArray());
+ new AFPParser(false).read(bis, sb);
+ return sb.toString();
+ }
+
+ private ByteArrayOutputStream getAFPBytes(String fo) throws Exception {
FopFactoryBuilder confBuilder = new FopConfParser(
new ByteArrayInputStream(fopxconf.getBytes()),
EnvironmentalProfileFactory.createRestrictedIO(new URI("."),
@@ -243,11 +288,7 @@ public class AFPTrueTypeTestCase {
Result res = new SAXResult(fop.getDefaultHandler());
transformer.transform(src, res);
bos.close();
-
- StringBuilder sb = new StringBuilder();
- InputStream bis = new ByteArrayInputStream(bos.toByteArray());
- new AFPParser(false).read(bis, sb);
- return sb.toString();
+ return bos;
}
class MyResourceResolver implements ResourceResolver {