aboutsummaryrefslogtreecommitdiffstats
path: root/fop-core/src/main/java
diff options
context:
space:
mode:
authorSimon Steiner <ssteiner@apache.org>2024-11-07 10:08:50 +0000
committerSimon Steiner <ssteiner@apache.org>2024-11-07 10:11:05 +0000
commit8c1be2a681164d59a94200056c4fce1f9d7defbc (patch)
treeee2deba4678c07d4a1a9935e7fe527e9c1399085 /fop-core/src/main/java
parent3294f6046a6cd2f776f58eeeb773f323a7dceaa4 (diff)
downloadxmlgraphics-fop-8c1be2a681164d59a94200056c4fce1f9d7defbc.tar.gz
xmlgraphics-fop-8c1be2a681164d59a94200056c4fce1f9d7defbc.zip
FOP-3180: SVG Glyph positions ignored when using a custom font by João André Gonçalves
Diffstat (limited to 'fop-core/src/main/java')
-rw-r--r--fop-core/src/main/java/org/apache/fop/svg/NativeTextPainter.java28
-rw-r--r--fop-core/src/main/java/org/apache/fop/svg/PDFTextPainter.java77
-rw-r--r--fop-core/src/main/java/org/apache/fop/svg/font/FOPGVTGlyphVector.java4
-rw-r--r--fop-core/src/main/java/org/apache/fop/svg/text/ComplexGlyphLayout.java27
4 files changed, 81 insertions, 55 deletions
diff --git a/fop-core/src/main/java/org/apache/fop/svg/NativeTextPainter.java b/fop-core/src/main/java/org/apache/fop/svg/NativeTextPainter.java
index e6a1b43dd..09cca6a03 100644
--- a/fop-core/src/main/java/org/apache/fop/svg/NativeTextPainter.java
+++ b/fop-core/src/main/java/org/apache/fop/svg/NativeTextPainter.java
@@ -134,7 +134,6 @@ public abstract class NativeTextPainter extends StrokingTextPainter {
}
protected void writeGlyphs(FOPGVTGlyphVector gv, GeneralPath debugShapes) throws IOException {
- AffineTransform localTransform = new AffineTransform();
Point2D prevPos = null;
AffineTransform prevGlyphTransform = null;
font = ((FOPGVTFont) gv.getFont()).getFont();
@@ -142,6 +141,8 @@ public abstract class NativeTextPainter extends StrokingTextPainter {
if (!gv.isGlyphVisible(index)) {
continue;
}
+
+ char glyph = (char) gv.getGlyphCode(index);
Point2D glyphPos = gv.getGlyphPosition(index);
AffineTransform glyphTransform = gv.getGlyphTransform(index);
@@ -156,22 +157,27 @@ public abstract class NativeTextPainter extends StrokingTextPainter {
debugShapes.append(sh, false);
}
- //Exact position of the glyph
- localTransform.setToIdentity();
- localTransform.translate(glyphPos.getX(), glyphPos.getY());
- if (glyphTransform != null) {
- localTransform.concatenate(glyphTransform);
- }
- localTransform.scale(1, -1);
-
positionGlyph(prevPos, glyphPos, glyphTransform != null || prevGlyphTransform != null);
- char glyph = (char) gv.getGlyphCode(index);
+
//Update last position
prevPos = glyphPos;
prevGlyphTransform = glyphTransform;
- writeGlyph(glyph, localTransform);
+ writeGlyph(glyph, getLocalTransform(glyphPos, glyphTransform));
+ }
+ }
+
+ protected AffineTransform getLocalTransform(Point2D glyphPos, AffineTransform glyphTransform) {
+ //Exact position of the glyph
+ AffineTransform localTransform = new AffineTransform();
+ localTransform.setToIdentity();
+ localTransform.translate(glyphPos.getX(), glyphPos.getY());
+ if (glyphTransform != null) {
+ localTransform.concatenate(glyphTransform);
}
+ localTransform.scale(1, -1);
+
+ return localTransform;
}
@Override
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 301af2070..ef5aac323 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
@@ -31,7 +31,6 @@ 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;
@@ -48,6 +47,8 @@ import org.apache.fop.svg.font.FOPGVTGlyphVector;
*/
class PDFTextPainter extends NativeTextPainter {
+ private static final int[] PA_ZERO = new int[4];
+
private PDFGraphics2D pdf;
private PDFTextUtil textUtil;
@@ -108,40 +109,50 @@ class PDFTextPainter extends NativeTextPainter {
pdf.writeClip(clip);
}
- private static int[] paZero = new int[4];
-
+ @Override
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);
- 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;
+ Point2D prevPos = null;
+ AffineTransform prevGlyphTransform = null;
+ font = ((FOPGVTFont) gv.getFont()).getFont();
+ int[][] glyphPositionAdjustments = gv.getGlyphPositionAdjustments();
+ double glyphXPos = 0f;
+ double glyphYPos = 0f;
+ double prevAdjustedGlyphXPos = 0f;
+ double prevAdjustedGlyphYPos = 0f;
+ for (int index = 0; index < gv.getNumGlyphs(); index++) {
+ if (!gv.isGlyphVisible(index)) {
+ continue;
+ }
+ Point2D glyphPos = gv.getGlyphPosition(index);
+ AffineTransform glyphTransform = gv.getGlyphTransform(index);
+ int[] positionAdjust = ((index > glyphPositionAdjustments.length)
+ || (glyphPositionAdjustments[index] == null)) ? PA_ZERO : glyphPositionAdjustments[index];
+ if (log.isTraceEnabled()) {
+ log.trace("pos " + glyphPos + ", transform " + glyphTransform);
+ }
+
+ positionGlyph(prevPos, glyphPos, glyphTransform != null || prevGlyphTransform != null);
+
+ char glyph = (char) gv.getGlyphCode(index);
+ double adjustedGlyphXPos = glyphXPos + positionAdjust[0];
+ double adjustedGlyphYPos = glyphYPos + positionAdjust[1];
+ double tdXPos = (adjustedGlyphXPos - prevAdjustedGlyphXPos) / 1000f;
+ double tdYPos = (adjustedGlyphYPos - prevAdjustedGlyphYPos) / 1000f;
+
+ textUtil.writeTd(tdXPos, tdYPos);
+
+ writeGlyph(glyph, getLocalTransform(glyphPos, glyphTransform));
+
+ //Update last position
+ prevPos = glyphPos;
+ prevGlyphTransform = glyphTransform;
+ glyphXPos = glyphPos.getX() + positionAdjust[2];
+ glyphYPos = glyphPos.getY() + positionAdjust[3];
+ prevAdjustedGlyphXPos = adjustedGlyphXPos;
+ prevAdjustedGlyphYPos = adjustedGlyphYPos;
}
}
}
@@ -193,9 +204,7 @@ class PDFTextPainter extends NativeTextPainter {
|| reposition);
if (!repositionNextGlyph) {
double xdiff = glyphPos.getX() - prevPos.getX();
- //Width of previous character
- double cw = prevVisibleGlyphWidth;
- double effxdiff = (1000 * xdiff) - cw;
+ double effxdiff = (1000 * xdiff) - prevVisibleGlyphWidth;
if (effxdiff != 0) {
double adjust = (-effxdiff / font.getFontSize());
textUtil.adjustGlyphTJ(adjust * 1000);
diff --git a/fop-core/src/main/java/org/apache/fop/svg/font/FOPGVTGlyphVector.java b/fop-core/src/main/java/org/apache/fop/svg/font/FOPGVTGlyphVector.java
index 106469258..0f92be578 100644
--- a/fop-core/src/main/java/org/apache/fop/svg/font/FOPGVTGlyphVector.java
+++ b/fop-core/src/main/java/org/apache/fop/svg/font/FOPGVTGlyphVector.java
@@ -320,6 +320,10 @@ public class FOPGVTGlyphVector implements GVTGlyphVector {
return gposAdjustments;
}
+ public List getAssociations() {
+ return associations;
+ }
+
public Point2D getGlyphPosition(int glyphIndex) {
int positionIndex = glyphIndex * 2;
return new Point2D.Float(positions[positionIndex], positions[positionIndex + 1]);
diff --git a/fop-core/src/main/java/org/apache/fop/svg/text/ComplexGlyphLayout.java b/fop-core/src/main/java/org/apache/fop/svg/text/ComplexGlyphLayout.java
index b90e89b01..a35b41250 100644
--- a/fop-core/src/main/java/org/apache/fop/svg/text/ComplexGlyphLayout.java
+++ b/fop-core/src/main/java/org/apache/fop/svg/text/ComplexGlyphLayout.java
@@ -22,14 +22,16 @@ package org.apache.fop.svg.text;
import java.awt.font.FontRenderContext;
import java.awt.geom.Point2D;
import java.text.AttributedCharacterIterator;
+import java.util.List;
import org.apache.batik.bridge.GlyphLayout;
import org.apache.batik.gvt.font.GVTFont;
-import org.apache.batik.gvt.font.GVTGlyphVector;
import org.apache.batik.gvt.text.GVTAttributedCharacterIterator;
+import org.apache.fop.complexscripts.util.CharAssociation;
import org.apache.fop.fonts.Font;
import org.apache.fop.svg.font.FOPGVTFont;
+import org.apache.fop.svg.font.FOPGVTGlyphVector;
public class ComplexGlyphLayout extends GlyphLayout {
@@ -39,16 +41,21 @@ public class ComplexGlyphLayout extends GlyphLayout {
}
@Override
- protected void doExplicitGlyphLayout() {
- GVTGlyphVector gv = this.gv;
- gv.performDefaultLayout();
- int ng = gv.getNumGlyphs();
- if (ng > 0) {
- this.advance = gv.getGlyphPosition(ng);
- } else {
- this.advance = new Point2D.Float(0, 0);
+ protected int getAciIndex(int aciIndex, int loopIndex) {
+ if (gv instanceof FOPGVTGlyphVector) {
+ List associations = ((FOPGVTGlyphVector) gv).getAssociations();
+ // this method is called at the end of the cycle, therefore we still have the index of the current cycle
+ // since we are trying to determine the aci index for the next interation, we need to add 1 to the index
+ // the parent method does that automatically when it tries to get the character count
+ int nextIndex = loopIndex + 1;
+ if (nextIndex < associations.size() && associations.get(nextIndex) instanceof CharAssociation) {
+ CharAssociation association = (CharAssociation) associations.get(nextIndex);
+ return association.getStart();
+ }
}
- this.layoutApplied = true;
+
+ //will only be used on the last iteration. the loop will stop after this and the value will not be used
+ return super.getAciIndex(aciIndex, loopIndex);
}
public static final boolean mayRequireComplexLayout(AttributedCharacterIterator aci) {