diff options
author | Simon Steiner <ssteiner@apache.org> | 2022-01-28 10:27:59 +0000 |
---|---|---|
committer | Simon Steiner <ssteiner@apache.org> | 2022-01-28 10:27:59 +0000 |
commit | 999ca17b4f4c879db6e40c58cca8763129bd4b07 (patch) | |
tree | 32eda3c25d7a04aaf06573acc1ed9b6218a015d2 /fop-core/src | |
parent | fa96721ca8a7a8ed0d4de31e919c28921444c9d9 (diff) | |
download | xmlgraphics-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')
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 { |