From 6f6e58d7b89b04847f37ad887aa2b7235c2b484f Mon Sep 17 00:00:00 2001 From: Simon Steiner Date: Tue, 11 Jul 2023 13:02:18 +0100 Subject: FOP-3042: SVG text containing certain glyphs isn't rendered by Dave Roxburgh --- .../java/org/apache/fop/svg/PDFTextPainter.java | 50 +++++++++---------- .../org/apache/fop/svg/PDFTextPainterTestCase.java | 57 ++++++++++++++++++++++ 2 files changed, 81 insertions(+), 26 deletions(-) diff --git a/fop-core/src/main/java/org/apache/fop/svg/PDFTextPainter.java b/fop-core/src/main/java/org/apache/fop/svg/PDFTextPainter.java index e46642892..301af2070 100644 --- a/fop-core/src/main/java/org/apache/fop/svg/PDFTextPainter.java +++ b/fop-core/src/main/java/org/apache/fop/svg/PDFTextPainter.java @@ -118,32 +118,30 @@ class PDFTextPainter extends NativeTextPainter { String fk = gvtFont.getFontKey(); Font f = gvtFont.getFont(); Point2D initialPos = gv.getGlyphPosition(0); - if (f.isMultiByte()) { - int fs = f.getFontSize(); - float fsPoints = fs / 1000f; - double xc = 0f; - double yc = 0f; - double xoLast = 0f; - double yoLast = 0f; - textUtil.writeTextMatrix(new AffineTransform(1, 0, 0, -1, initialPos.getX(), initialPos.getY())); - textUtil.updateTf(fk, fsPoints, true, false); - int[][] dp = gv.getGlyphPositionAdjustments(); - for (int i = 0, n = gv.getNumGlyphs(); i < n; i++) { - int gc = gv.getGlyphCode(i); - int[] pa = ((i > dp.length) || (dp[i] == null)) ? paZero : dp[i]; - double xo = xc + pa[0]; - double yo = yc + pa[1]; - double xa = f.getWidth(gc); - double ya = 0; - double xd = (xo - xoLast) / 1000f; - double yd = (yo - yoLast) / 1000f; - textUtil.writeTd(xd, yd); - textUtil.writeTj((char) gc, true, false); - xc += xa + pa[2]; - yc += ya + pa[3]; - xoLast = xo; - yoLast = yo; - } + int fs = f.getFontSize(); + float fsPoints = fs / 1000f; + double xc = 0f; + double yc = 0f; + double xoLast = 0f; + double yoLast = 0f; + textUtil.writeTextMatrix(new AffineTransform(1, 0, 0, -1, initialPos.getX(), initialPos.getY())); + textUtil.updateTf(fk, fsPoints, f.isMultiByte(), false); + int[][] dp = gv.getGlyphPositionAdjustments(); + for (int i = 0, n = gv.getNumGlyphs(); i < n; i++) { + int gc = gv.getGlyphCode(i); + int[] pa = ((i > dp.length) || (dp[i] == null)) ? paZero : dp[i]; + double xo = xc + pa[0]; + double yo = yc + pa[1]; + double xa = f.getWidth(gc); + double ya = 0; + double xd = (xo - xoLast) / 1000f; + double yd = (yo - yoLast) / 1000f; + textUtil.writeTd(xd, yd); + textUtil.writeTj((char) gc, f.isMultiByte(), false); + xc += xa + pa[2]; + yc += ya + pa[3]; + xoLast = xo; + yoLast = yo; } } } diff --git a/fop-core/src/test/java/org/apache/fop/svg/PDFTextPainterTestCase.java b/fop-core/src/test/java/org/apache/fop/svg/PDFTextPainterTestCase.java index 3e64cb58f..317e969d2 100644 --- a/fop-core/src/test/java/org/apache/fop/svg/PDFTextPainterTestCase.java +++ b/fop-core/src/test/java/org/apache/fop/svg/PDFTextPainterTestCase.java @@ -20,16 +20,29 @@ package org.apache.fop.svg; import java.awt.Graphics2D; +import java.awt.Point; +import java.awt.geom.AffineTransform; +import java.awt.geom.GeneralPath; import java.io.StringWriter; +import org.junit.Assert; import org.junit.Test; +import static org.mockito.Mockito.mock; +import static org.mockito.Mockito.when; + import org.apache.batik.bridge.TextPainter; +import org.apache.batik.gvt.text.TextPaintInfo; import org.apache.xmlgraphics.java2d.GraphicContext; +import org.apache.fop.fonts.Font; import org.apache.fop.fonts.FontInfo; +import org.apache.fop.fonts.FontTriplet; +import org.apache.fop.fonts.base14.Base14FontCollection; import org.apache.fop.pdf.PDFDocument; +import org.apache.fop.svg.font.FOPGVTFont; +import org.apache.fop.svg.font.FOPGVTGlyphVector; public class PDFTextPainterTestCase extends NativeTextPainterTest { @@ -145,4 +158,48 @@ public class PDFTextPainterTestCase extends NativeTextPainterTest { .addOperatorMatch("TJ", "[(IJ)] TJ\n")); } + /** + * Tests that glyph vectors in single-byte fonts with glyph position adjustments are properly written. + * @throws Exception + */ + @Test + public void testSingleByteAdjustments() throws Exception { + FontInfo fontInfo = new FontInfo(); + new Base14FontCollection(true).setup(0, fontInfo); + + PDFTextPainter painter = new PDFTextPainter(fontInfo); + PDFGraphics2D g2d = mock(PDFGraphics2D.class); + g2d.currentStream = new StringWriter(); + painter.preparePainting(g2d); + painter.setInitialTransform(new AffineTransform()); + TextPaintInfo tpi = new TextPaintInfo(); + tpi.visible = true; + painter.tpi = tpi; + painter.beginTextObject(); + + FOPGVTGlyphVector mockGV = mock(FOPGVTGlyphVector.class); + FontTriplet triplet = new FontTriplet("Times", "normal", 400); + Font font = fontInfo.getFontInstance(triplet, 12); + + FOPGVTFont mockGvtFont = mock(FOPGVTFont.class); + org.apache.fop.fonts.FontMetrics fontMetrics = font.getFontMetrics(); + when(mockGvtFont.getFont()).thenReturn(new Font("Times", triplet, fontMetrics, 12)); + when(mockGvtFont.getFontKey()).thenReturn("Times"); + + when(mockGV.getFont()).thenReturn(mockGvtFont); + when(mockGV.getGlyphPositionAdjustments()).thenReturn(new int[][] {{2, 3, 4, 5}, {6, 7, 8, 9}}); + when(mockGV.getGlyphPosition(0)).thenReturn(new Point(0, 0)); + when(mockGV.getNumGlyphs()).thenReturn(1); + when(mockGV.getGlyphCode(0)).thenReturn(1); + + GeneralPath gp = new GeneralPath(); + + painter.writeGlyphs(mockGV, gp); + Assert.assertEquals("BT\n" + + "3 Tr\n" + + "1 0 0 -1 0 0 Tm /Times 0.012 Tf\n" + + "0.002 0.003 Td\n" + + "(\\1) Tj\n", + g2d.currentStream.toString()); + } } -- cgit v1.2.3