aboutsummaryrefslogtreecommitdiffstats
path: root/src/java/org/apache
diff options
context:
space:
mode:
authorGlenn Adams <gadams@apache.org>2014-09-20 19:02:18 +0000
committerGlenn Adams <gadams@apache.org>2014-09-20 19:02:18 +0000
commitec1da9e25ca22853d9bd9be9d4bb6a39dea58ec3 (patch)
treef57ed7dd40eab7d39d1ac3648f22d8ca057552ba /src/java/org/apache
parent6e276ed8620789b5365c682c0fa8d3fe440647fe (diff)
downloadxmlgraphics-fop-ec1da9e25ca22853d9bd9be9d4bb6a39dea58ec3.tar.gz
xmlgraphics-fop-ec1da9e25ca22853d9bd9be9d4bb6a39dea58ec3.zip
FOP-2391: fix NSM reordering issue and ensure same PDF output as XSL-FO code path (using Td/Tj operators)
git-svn-id: https://svn.apache.org/repos/asf/xmlgraphics/fop/trunk@1626491 13f79535-47bb-0310-9956-ffa450edef68
Diffstat (limited to 'src/java/org/apache')
-rw-r--r--src/java/org/apache/fop/fonts/Font.java8
-rw-r--r--src/java/org/apache/fop/fonts/FontMetrics.java7
-rw-r--r--src/java/org/apache/fop/svg/NativeTextPainter.java56
-rw-r--r--src/java/org/apache/fop/svg/PDFTextPainter.java45
-rw-r--r--src/java/org/apache/fop/svg/font/ComplexGlyphVector.java20
-rw-r--r--src/java/org/apache/fop/svg/font/FOPGVTFont.java14
-rw-r--r--src/java/org/apache/fop/svg/font/FOPGVTFontFamily.java12
-rw-r--r--src/java/org/apache/fop/svg/font/FOPGVTGlyphVector.java9
8 files changed, 137 insertions, 34 deletions
diff --git a/src/java/org/apache/fop/fonts/Font.java b/src/java/org/apache/fop/fonts/Font.java
index 305e8f78a..399be056a 100644
--- a/src/java/org/apache/fop/fonts/Font.java
+++ b/src/java/org/apache/fop/fonts/Font.java
@@ -103,6 +103,14 @@ public class Font implements Substitutable, Positionable {
}
/**
+ * Determines whether the font is a multibyte font.
+ * @return True if it is multibyte
+ */
+ public boolean isMultiByte() {
+ return getFontMetrics().isMultiByte();
+ }
+
+ /**
* Returns the font's ascender.
* @return the ascender
*/
diff --git a/src/java/org/apache/fop/fonts/FontMetrics.java b/src/java/org/apache/fop/fonts/FontMetrics.java
index 4b1fb1f1f..ce00e34b9 100644
--- a/src/java/org/apache/fop/fonts/FontMetrics.java
+++ b/src/java/org/apache/fop/fonts/FontMetrics.java
@@ -190,4 +190,11 @@ public interface FontMetrics {
* @return true if feature supported (and has at least one lookup)
*/
boolean hasFeature(int tableType, String script, String language, String feature);
+
+ /**
+ * Determines whether the font is a multibyte font.
+ * @return True if it is multibyte
+ */
+ boolean isMultiByte();
+
}
diff --git a/src/java/org/apache/fop/svg/NativeTextPainter.java b/src/java/org/apache/fop/svg/NativeTextPainter.java
index 18c140163..cb96368c8 100644
--- a/src/java/org/apache/fop/svg/NativeTextPainter.java
+++ b/src/java/org/apache/fop/svg/NativeTextPainter.java
@@ -51,6 +51,7 @@ import org.apache.fop.fonts.Font;
import org.apache.fop.fonts.FontInfo;
import org.apache.fop.svg.font.FOPFontFamilyResolverImpl;
import org.apache.fop.svg.font.FOPGVTFont;
+import org.apache.fop.svg.font.FOPGVTGlyphVector;
import org.apache.fop.svg.text.BidiAttributedCharacterIterator;
import org.apache.fop.svg.text.ComplexGlyphLayout;
import org.apache.fop.util.CharUtilities;
@@ -64,8 +65,6 @@ public abstract class NativeTextPainter extends StrokingTextPainter {
/** the logger for this class */
protected static final Log log = LogFactory.getLog(NativeTextPainter.class);
- private static final boolean DEBUG = false;
-
/** the font collection */
protected final FontInfo fontInfo;
@@ -99,9 +98,9 @@ public abstract class NativeTextPainter extends StrokingTextPainter {
* @throws IOException if an I/O error occurs while rendering the text
*/
protected final void paintTextRun(TextRun textRun, Graphics2D g2d) throws IOException {
+ logTextRun(textRun);
AttributedCharacterIterator runaci = textRun.getACI();
runaci.first();
-
tpi = (TextPaintInfo) runaci.getAttribute(PAINT_INFO);
if (tpi == null || !tpi.visible) {
return;
@@ -109,36 +108,36 @@ public abstract class NativeTextPainter extends StrokingTextPainter {
if (tpi.composite != null) {
g2d.setComposite(tpi.composite);
}
-
- //------------------------------------
TextSpanLayout layout = textRun.getLayout();
- logTextRun(runaci, layout);
- runaci.first(); //Reset ACI
-
- GeneralPath debugShapes = null;
- if (DEBUG) {
- debugShapes = new GeneralPath();
- }
-
- preparePainting(g2d);
-
GVTGlyphVector gv = layout.getGlyphVector();
if (!(gv.getFont() instanceof FOPGVTFont)) {
assert gv.getFont() == null || gv.getFont() instanceof SVGGVTFont;
//Draw using Java2D when no native fonts are available
textRun.getLayout().draw(g2d);
return;
+ } else {
+ GeneralPath debugShapes = log.isDebugEnabled() ? new GeneralPath() : null;
+ preparePainting(g2d);
+ saveGraphicsState();
+ setInitialTransform(g2d.getTransform());
+ clip(g2d.getClip());
+ beginTextObject();
+ writeGlyphs((FOPGVTGlyphVector) gv, debugShapes);
+ endTextObject();
+ restoreGraphicsState();
+ if (debugShapes != null) {
+ g2d.setStroke(new BasicStroke(0));
+ g2d.setColor(Color.LIGHT_GRAY);
+ g2d.draw(debugShapes);
+ }
}
- font = ((FOPGVTFont) gv.getFont()).getFont();
-
- saveGraphicsState();
- setInitialTransform(g2d.getTransform());
- clip(g2d.getClip());
- beginTextObject();
+ }
+ protected void writeGlyphs(FOPGVTGlyphVector gv, GeneralPath debugShapes) throws IOException {
AffineTransform localTransform = new AffineTransform();
Point2D prevPos = null;
AffineTransform prevGlyphTransform = null;
+ font = ((FOPGVTFont) gv.getFont()).getFont();
for (int index = 0, c = gv.getNumGlyphs(); index < c; index++) {
if (!gv.isGlyphVisible(index)) {
continue;
@@ -149,7 +148,7 @@ public abstract class NativeTextPainter extends StrokingTextPainter {
if (log.isTraceEnabled()) {
log.trace("pos " + glyphPos + ", transform " + glyphTransform);
}
- if (DEBUG) {
+ if (debugShapes != null) {
Shape sh = gv.getGlyphLogicalBounds(index);
if (sh == null) {
sh = new Ellipse2D.Double(glyphPos.getX(), glyphPos.getY(), 2, 2);
@@ -173,14 +172,6 @@ public abstract class NativeTextPainter extends StrokingTextPainter {
writeGlyph(glyph, localTransform);
}
- endTextObject();
- restoreGraphicsState();
- if (DEBUG) {
- //Paint debug shapes
- g2d.setStroke(new BasicStroke(0));
- g2d.setColor(Color.LIGHT_GRAY);
- g2d.draw(debugShapes);
- }
}
@Override
@@ -348,7 +339,10 @@ public abstract class NativeTextPainter extends StrokingTextPainter {
* @param runaci an attributed character iterator
* @param layout a text span layout
*/
- protected final void logTextRun(AttributedCharacterIterator runaci, TextSpanLayout layout) {
+ protected final void logTextRun(TextRun textRun) {
+ AttributedCharacterIterator runaci = textRun.getACI();
+ TextSpanLayout layout = textRun.getLayout();
+ runaci.first();
if (log.isTraceEnabled()) {
int charCount = runaci.getEndIndex() - runaci.getBeginIndex();
log.trace("================================================");
diff --git a/src/java/org/apache/fop/svg/PDFTextPainter.java b/src/java/org/apache/fop/svg/PDFTextPainter.java
index c5fa9f04e..0320438f8 100644
--- a/src/java/org/apache/fop/svg/PDFTextPainter.java
+++ b/src/java/org/apache/fop/svg/PDFTextPainter.java
@@ -25,11 +25,16 @@ import java.awt.Paint;
import java.awt.Shape;
import java.awt.Stroke;
import java.awt.geom.AffineTransform;
+import java.awt.geom.GeneralPath;
import java.awt.geom.Point2D;
+import java.io.IOException;
import org.apache.batik.gvt.text.TextPaintInfo;
+import org.apache.fop.fonts.Font;
import org.apache.fop.fonts.FontInfo;
+import org.apache.fop.svg.font.FOPGVTFont;
+import org.apache.fop.svg.font.FOPGVTGlyphVector;
/**
* Renders the attributed character iterator of a {@link org.apache.batik.gvt.TextNode}.
@@ -104,6 +109,46 @@ class PDFTextPainter extends NativeTextPainter {
pdf.writeClip(clip);
}
+ private static int[] paZero = new int[4];
+
+ protected void writeGlyphs(FOPGVTGlyphVector gv, GeneralPath debugShapes) throws IOException {
+ if (gv.getGlyphPositionAdjustments() == null) {
+ super.writeGlyphs(gv, debugShapes);
+ } else {
+ FOPGVTFont gvtFont = (FOPGVTFont) gv.getFont();
+ 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);
+ 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);
+ xc += xa + pa[2];
+ yc += ya + pa[3];
+ xoLast = xo;
+ yoLast = yo;
+ }
+ }
+ }
+ }
+
@Override
protected void beginTextObject() {
applyColorAndPaint(tpi);
diff --git a/src/java/org/apache/fop/svg/font/ComplexGlyphVector.java b/src/java/org/apache/fop/svg/font/ComplexGlyphVector.java
index 8fa705e4c..567f9726a 100644
--- a/src/java/org/apache/fop/svg/font/ComplexGlyphVector.java
+++ b/src/java/org/apache/fop/svg/font/ComplexGlyphVector.java
@@ -64,6 +64,9 @@ class ComplexGlyphVector extends FOPGVTGlyphVector {
if (associations != null) {
Collections.reverse(associations);
}
+ if (gposAdjustments != null) {
+ reverse(gposAdjustments);
+ }
if (positions != null) {
reverse(positions);
}
@@ -139,6 +142,15 @@ class ComplexGlyphVector extends FOPGVTGlyphVector {
}
}
+ private static void reverse(int[][] iaa) {
+ for (int i = 0, n = iaa.length, m = n / 2; i < m; i++) {
+ int k = n - i - 1;
+ int[] t = iaa [ k ];
+ iaa [ k ] = iaa [ i ];
+ iaa [ i ] = t;
+ }
+ }
+
private static void reverse(float[] fa) {
int skip = 2;
int numPositions = fa.length / skip;
@@ -153,8 +165,12 @@ class ComplexGlyphVector extends FOPGVTGlyphVector {
}
}
float runAdvanceX = fa [ 0 ];
- for (int i = 0, n = fa.length; i < n; i += 2) {
- fa [ i ] = runAdvanceX - fa [ i ];
+ for (int i = 0, n = numPositions; i < n; ++i) {
+ int k = i * 2;
+ fa [ k + 0 ] = runAdvanceX - fa [ k + 0 ];
+ if (i > 0) {
+ fa [ k - 1 ] = fa [ k + 1 ];
+ }
}
}
diff --git a/src/java/org/apache/fop/svg/font/FOPGVTFont.java b/src/java/org/apache/fop/svg/font/FOPGVTFont.java
index 76f77d367..fd92e36bc 100644
--- a/src/java/org/apache/fop/svg/font/FOPGVTFont.java
+++ b/src/java/org/apache/fop/svg/font/FOPGVTFont.java
@@ -31,7 +31,9 @@ import org.apache.batik.gvt.font.GVTLineMetrics;
import org.apache.batik.gvt.text.GVTAttributedCharacterIterator;
import org.apache.fop.fonts.Font;
+import org.apache.fop.fonts.FontInfo;
import org.apache.fop.fonts.FontMetrics;
+import org.apache.fop.fonts.FontTriplet;
public class FOPGVTFont implements GVTFont {
@@ -122,6 +124,18 @@ public class FOPGVTFont implements GVTFont {
throw new UnsupportedOperationException("Not implemented");
}
+ public FontInfo getFontInfo() {
+ return ((FOPGVTFontFamily) fontFamily).getFontInfo();
+ }
+
+ public String getFontKey() {
+ return ((FOPGVTFontFamily) fontFamily).getFontKey();
+ }
+
+ public FontTriplet getFontTriplet() {
+ return ((FOPGVTFontFamily) fontFamily).getFontTriplet();
+ }
+
public String getFamilyName() {
return fontFamily.getFamilyName();
}
diff --git a/src/java/org/apache/fop/svg/font/FOPGVTFontFamily.java b/src/java/org/apache/fop/svg/font/FOPGVTFontFamily.java
index 5be9419d3..b9351af44 100644
--- a/src/java/org/apache/fop/svg/font/FOPGVTFontFamily.java
+++ b/src/java/org/apache/fop/svg/font/FOPGVTFontFamily.java
@@ -47,6 +47,18 @@ public class FOPGVTFontFamily implements GVTFontFamily {
this.fontFace = fontFace;
}
+ public FontInfo getFontInfo() {
+ return fontInfo;
+ }
+
+ public FontTriplet getFontTriplet() {
+ return fontTriplet;
+ }
+
+ public String getFontKey() {
+ return fontInfo.getInternalFontKey(fontTriplet);
+ }
+
public String getFamilyName() {
return familyName;
}
diff --git a/src/java/org/apache/fop/svg/font/FOPGVTGlyphVector.java b/src/java/org/apache/fop/svg/font/FOPGVTGlyphVector.java
index 2b2115935..77bdec48d 100644
--- a/src/java/org/apache/fop/svg/font/FOPGVTGlyphVector.java
+++ b/src/java/org/apache/fop/svg/font/FOPGVTGlyphVector.java
@@ -47,7 +47,7 @@ import org.apache.fop.fonts.GlyphMapping;
import org.apache.fop.fonts.TextFragment;
import org.apache.fop.traits.MinOptMax;
-class FOPGVTGlyphVector implements GVTGlyphVector {
+public class FOPGVTGlyphVector implements GVTGlyphVector {
protected final TextFragment text;
@@ -63,6 +63,8 @@ class FOPGVTGlyphVector implements GVTGlyphVector {
protected List associations;
+ protected int[][] gposAdjustments;
+
protected float[] positions;
protected Rectangle2D[] boundingBoxes;
@@ -94,6 +96,7 @@ class FOPGVTGlyphVector implements GVTGlyphVector {
mapping.mapping != null ? new StringCharacterIterator(mapping.mapping) : text.getIterator();
this.glyphs = buildGlyphs(f, glyphAsCharIter);
this.associations = mapping.associations;
+ this.gposAdjustments = mapping.gposAdjustments;
this.positions = buildGlyphPositions(glyphAsCharIter, mapping.gposAdjustments, letterSpaceAdjustments);
this.glyphVisibilities = new boolean[this.glyphs.length];
Arrays.fill(glyphVisibilities, true);
@@ -304,6 +307,10 @@ class FOPGVTGlyphVector implements GVTGlyphVector {
throw new UnsupportedOperationException();
}
+ public int[][] getGlyphPositionAdjustments() {
+ return gposAdjustments;
+ }
+
public Point2D getGlyphPosition(int glyphIndex) {
int positionIndex = glyphIndex * 2;
return new Point2D.Float(positions[positionIndex], positions[positionIndex + 1]);