You are viewing a plain text version of this content. The canonical link for it is here.
Posted to fop-commits@xmlgraphics.apache.org by vh...@apache.org on 2013/07/29 23:45:23 UTC
svn commit: r1508208 [8/10] - in
/xmlgraphics/fop/branches/Temp_FopFontsForSVG: ./ lib/ src/codegen/fonts/
src/java/org/apache/fop/afp/ src/java/org/apache/fop/afp/fonts/
src/java/org/apache/fop/afp/goca/ src/java/org/apache/fop/afp/svg/
src/java/org/a...
Modified: xmlgraphics/fop/branches/Temp_FopFontsForSVG/src/java/org/apache/fop/render/java2d/Java2DFontMetrics.java
URL: http://svn.apache.org/viewvc/xmlgraphics/fop/branches/Temp_FopFontsForSVG/src/java/org/apache/fop/render/java2d/Java2DFontMetrics.java?rev=1508208&r1=1508207&r2=1508208&view=diff
==============================================================================
--- xmlgraphics/fop/branches/Temp_FopFontsForSVG/src/java/org/apache/fop/render/java2d/Java2DFontMetrics.java (original)
+++ xmlgraphics/fop/branches/Temp_FopFontsForSVG/src/java/org/apache/fop/render/java2d/Java2DFontMetrics.java Mon Jul 29 21:45:20 2013
@@ -223,6 +223,26 @@ public class Java2DFontMetrics {
return xHeight * 1000;
}
+ public int getUnderlinePosition(String family, int style, int size) {
+ setFont(family, style, size);
+ return -Math.round(lineMetrics.getUnderlineOffset());
+ }
+
+ public int getUnderlineThickness(String family, int style, int size) {
+ setFont(family, style, size);
+ return Math.round(lineMetrics.getUnderlineThickness());
+ }
+
+ public int getStrikeoutPosition(String family, int style, int size) {
+ setFont(family, style, size);
+ return -Math.round(lineMetrics.getStrikethroughOffset());
+ }
+
+ public int getStrikeoutThickness(String family, int style, int size) {
+ setFont(family, style, size);
+ return Math.round(lineMetrics.getStrikethroughThickness());
+ }
+
/**
* Returns width (in 1/1000ths of point size) of character at
* code point i
Modified: xmlgraphics/fop/branches/Temp_FopFontsForSVG/src/java/org/apache/fop/render/java2d/Java2DSVGHandler.java
URL: http://svn.apache.org/viewvc/xmlgraphics/fop/branches/Temp_FopFontsForSVG/src/java/org/apache/fop/render/java2d/Java2DSVGHandler.java?rev=1508208&r1=1508207&r2=1508208&view=diff
==============================================================================
--- xmlgraphics/fop/branches/Temp_FopFontsForSVG/src/java/org/apache/fop/render/java2d/Java2DSVGHandler.java (original)
+++ xmlgraphics/fop/branches/Temp_FopFontsForSVG/src/java/org/apache/fop/render/java2d/Java2DSVGHandler.java Mon Jul 29 21:45:20 2013
@@ -31,6 +31,7 @@ import org.apache.commons.logging.LogFac
import org.apache.batik.bridge.BridgeContext;
import org.apache.batik.bridge.GVTBuilder;
import org.apache.batik.gvt.GraphicsNode;
+import org.apache.batik.gvt.font.DefaultFontFamilyResolver;
import org.apache.fop.image.loader.batik.BatikUtil;
import org.apache.fop.render.AbstractGenericSVGHandler;
@@ -128,8 +129,8 @@ public class Java2DSVGHandler extends Ab
int x = info.currentXPosition;
int y = info.currentYPosition;
-
- SVGUserAgent ua = new SVGUserAgent(context.getUserAgent(), new AffineTransform());
+ SVGUserAgent ua = new SVGUserAgent(context.getUserAgent(), DefaultFontFamilyResolver.SINGLETON,
+ new AffineTransform());
BridgeContext ctx = new BridgeContext(ua);
Modified: xmlgraphics/fop/branches/Temp_FopFontsForSVG/src/java/org/apache/fop/render/java2d/SystemFontMetricsMapper.java
URL: http://svn.apache.org/viewvc/xmlgraphics/fop/branches/Temp_FopFontsForSVG/src/java/org/apache/fop/render/java2d/SystemFontMetricsMapper.java?rev=1508208&r1=1508207&r2=1508208&view=diff
==============================================================================
--- xmlgraphics/fop/branches/Temp_FopFontsForSVG/src/java/org/apache/fop/render/java2d/SystemFontMetricsMapper.java (original)
+++ xmlgraphics/fop/branches/Temp_FopFontsForSVG/src/java/org/apache/fop/render/java2d/SystemFontMetricsMapper.java Mon Jul 29 21:45:20 2013
@@ -20,6 +20,7 @@
package org.apache.fop.render.java2d;
// Java
+import java.awt.Rectangle;
import java.util.Map;
import java.util.Set;
@@ -133,6 +134,22 @@ public class SystemFontMetricsMapper ext
return java2DFontMetrics.getXHeight(family, style, size);
}
+ public int getUnderlinePosition(int size) {
+ return java2DFontMetrics.getUnderlinePosition(family, style, size);
+ }
+
+ public int getUnderlineThickness(int size) {
+ return java2DFontMetrics.getUnderlineThickness(family, style, size);
+ }
+
+ public int getStrikeoutPosition(int size) {
+ return java2DFontMetrics.getStrikeoutPosition(family, style, size);
+ }
+
+ public int getStrikeoutThickness(int size) {
+ return java2DFontMetrics.getStrikeoutThickness(family, style, size);
+ }
+
/**
* {@inheritDoc}
*/
@@ -148,6 +165,10 @@ public class SystemFontMetricsMapper ext
return java2DFontMetrics.getWidths(family, style, Java2DFontMetrics.FONT_SIZE);
}
+ public Rectangle getBoundingBox(int glyphIndex, int size) {
+ throw new UnsupportedOperationException("Not implemented");
+ }
+
/**
* {@inheritDoc}
*/
Modified: xmlgraphics/fop/branches/Temp_FopFontsForSVG/src/java/org/apache/fop/render/pdf/PDFImageHandlerSVG.java
URL: http://svn.apache.org/viewvc/xmlgraphics/fop/branches/Temp_FopFontsForSVG/src/java/org/apache/fop/render/pdf/PDFImageHandlerSVG.java?rev=1508208&r1=1508207&r2=1508208&view=diff
==============================================================================
--- xmlgraphics/fop/branches/Temp_FopFontsForSVG/src/java/org/apache/fop/render/pdf/PDFImageHandlerSVG.java (original)
+++ xmlgraphics/fop/branches/Temp_FopFontsForSVG/src/java/org/apache/fop/render/pdf/PDFImageHandlerSVG.java Mon Jul 29 21:45:20 2013
@@ -52,6 +52,7 @@ import org.apache.fop.svg.PDFBridgeConte
import org.apache.fop.svg.PDFGraphics2D;
import org.apache.fop.svg.SVGEventProducer;
import org.apache.fop.svg.SVGUserAgent;
+import org.apache.fop.svg.font.FOPFontFamilyResolverImpl;
/**
* Image Handler implementation which handles SVG images.
@@ -76,7 +77,8 @@ public class PDFImageHandlerSVG implemen
}
final float uaResolution = userAgent.getSourceResolution();
- SVGUserAgent ua = new SVGUserAgent(userAgent, new AffineTransform());
+ SVGUserAgent ua = new SVGUserAgent(userAgent, new FOPFontFamilyResolverImpl(pdfContext.getFontInfo()),
+ new AffineTransform());
GVTBuilder builder = new GVTBuilder();
Modified: xmlgraphics/fop/branches/Temp_FopFontsForSVG/src/java/org/apache/fop/render/ps/AbstractPSTranscoder.java
URL: http://svn.apache.org/viewvc/xmlgraphics/fop/branches/Temp_FopFontsForSVG/src/java/org/apache/fop/render/ps/AbstractPSTranscoder.java?rev=1508208&r1=1508207&r2=1508208&view=diff
==============================================================================
--- xmlgraphics/fop/branches/Temp_FopFontsForSVG/src/java/org/apache/fop/render/ps/AbstractPSTranscoder.java (original)
+++ xmlgraphics/fop/branches/Temp_FopFontsForSVG/src/java/org/apache/fop/render/ps/AbstractPSTranscoder.java Mon Jul 29 21:45:20 2013
@@ -40,6 +40,7 @@ import org.apache.fop.apps.FOPException;
import org.apache.fop.fonts.FontInfo;
import org.apache.fop.svg.AbstractFOPTranscoder;
import org.apache.fop.svg.PDFDocumentGraphics2DConfigurator;
+import org.apache.fop.svg.font.FOPFontFamilyResolverImpl;
/**
* <p>This class enables to transcode an input to a PostScript document.</p>
@@ -115,6 +116,8 @@ public abstract class AbstractPSTranscod
this.fontInfo = PDFDocumentGraphics2DConfigurator.createFontInfo(
getEffectiveConfiguration(), useComplexScriptFeatures);
graphics.setCustomTextHandler(new NativeTextHandler(graphics, fontInfo));
+ ((FOPTranscoderUserAgent) userAgent).setFontFamilyResolver(
+ new FOPFontFamilyResolverImpl(fontInfo));
} catch (FOPException fe) {
throw new TranscoderException(fe);
}
Modified: xmlgraphics/fop/branches/Temp_FopFontsForSVG/src/java/org/apache/fop/render/ps/PSImageHandlerSVG.java
URL: http://svn.apache.org/viewvc/xmlgraphics/fop/branches/Temp_FopFontsForSVG/src/java/org/apache/fop/render/ps/PSImageHandlerSVG.java?rev=1508208&r1=1508207&r2=1508208&view=diff
==============================================================================
--- xmlgraphics/fop/branches/Temp_FopFontsForSVG/src/java/org/apache/fop/render/ps/PSImageHandlerSVG.java (original)
+++ xmlgraphics/fop/branches/Temp_FopFontsForSVG/src/java/org/apache/fop/render/ps/PSImageHandlerSVG.java Mon Jul 29 21:45:20 2013
@@ -41,6 +41,7 @@ import org.apache.fop.render.ImageHandle
import org.apache.fop.render.RenderingContext;
import org.apache.fop.svg.SVGEventProducer;
import org.apache.fop.svg.SVGUserAgent;
+import org.apache.fop.svg.font.FOPFontFamilyResolverImpl;
/**
* Image handler implementation which handles SVG images for PostScript output.
@@ -62,8 +63,8 @@ public class PSImageHandlerSVG implement
boolean strokeText = false;
//TODO Configure text stroking
- SVGUserAgent ua
- = new SVGUserAgent(context.getUserAgent(), new AffineTransform());
+ SVGUserAgent ua = new SVGUserAgent(context.getUserAgent(),
+ new FOPFontFamilyResolverImpl(psContext.getFontInfo()), new AffineTransform());
PSGraphics2D graphics = new PSGraphics2D(strokeText, gen);
graphics.setGraphicContext(new org.apache.xmlgraphics.java2d.GraphicContext());
Modified: xmlgraphics/fop/branches/Temp_FopFontsForSVG/src/java/org/apache/fop/render/ps/PSSVGHandler.java
URL: http://svn.apache.org/viewvc/xmlgraphics/fop/branches/Temp_FopFontsForSVG/src/java/org/apache/fop/render/ps/PSSVGHandler.java?rev=1508208&r1=1508207&r2=1508208&view=diff
==============================================================================
--- xmlgraphics/fop/branches/Temp_FopFontsForSVG/src/java/org/apache/fop/render/ps/PSSVGHandler.java (original)
+++ xmlgraphics/fop/branches/Temp_FopFontsForSVG/src/java/org/apache/fop/render/ps/PSSVGHandler.java Mon Jul 29 21:45:20 2013
@@ -249,8 +249,7 @@ public class PSSVGHandler extends Abstra
strokeText = cfg.getChild("stroke-text", true).getValueAsBoolean(strokeText);
}
- SVGUserAgent ua
- = new SVGUserAgent(context.getUserAgent(), new AffineTransform());
+ SVGUserAgent ua = new SVGUserAgent(context.getUserAgent(), null /* TODO */, new AffineTransform());
PSGraphics2D graphics = new PSGraphics2D(strokeText, gen);
graphics.setGraphicContext(new org.apache.xmlgraphics.java2d.GraphicContext());
Modified: xmlgraphics/fop/branches/Temp_FopFontsForSVG/src/java/org/apache/fop/render/ps/PSTextPainter.java
URL: http://svn.apache.org/viewvc/xmlgraphics/fop/branches/Temp_FopFontsForSVG/src/java/org/apache/fop/render/ps/PSTextPainter.java?rev=1508208&r1=1508207&r2=1508208&view=diff
==============================================================================
--- xmlgraphics/fop/branches/Temp_FopFontsForSVG/src/java/org/apache/fop/render/ps/PSTextPainter.java (original)
+++ xmlgraphics/fop/branches/Temp_FopFontsForSVG/src/java/org/apache/fop/render/ps/PSTextPainter.java Mon Jul 29 21:45:20 2013
@@ -19,25 +19,21 @@
package org.apache.fop.render.ps;
-import java.awt.BasicStroke;
import java.awt.Color;
import java.awt.Graphics2D;
import java.awt.Paint;
import java.awt.Shape;
import java.awt.Stroke;
import java.awt.geom.AffineTransform;
-import java.awt.geom.Ellipse2D;
-import java.awt.geom.GeneralPath;
import java.awt.geom.PathIterator;
import java.awt.geom.Point2D;
+import java.awt.geom.Point2D.Double;
import java.io.IOException;
-import java.text.AttributedCharacterIterator;
import java.util.Iterator;
+import java.util.LinkedList;
import java.util.List;
-import org.apache.batik.gvt.font.GVTGlyphVector;
import org.apache.batik.gvt.text.TextPaintInfo;
-import org.apache.batik.gvt.text.TextSpanLayout;
import org.apache.xmlgraphics.java2d.ps.PSGraphics2D;
import org.apache.xmlgraphics.ps.PSGenerator;
@@ -48,7 +44,6 @@ import org.apache.fop.fonts.FontMetrics;
import org.apache.fop.fonts.LazyFont;
import org.apache.fop.fonts.MultiByteFont;
import org.apache.fop.svg.NativeTextPainter;
-import org.apache.fop.util.CharUtilities;
import org.apache.fop.util.HexEncoder;
/**
@@ -62,10 +57,20 @@ import org.apache.fop.util.HexEncoder;
*/
public class PSTextPainter extends NativeTextPainter {
- private static final boolean DEBUG = false;
-
private FontResourceCache fontResources;
+ private PSGraphics2D ps;
+
+ private PSGenerator gen;
+
+ private TextUtil textUtil;
+
+ private boolean flushCurrentRun;
+
+ private PSTextRun psRun;
+
+ private Double relPos;
+
private static final AffineTransform IDENTITY_TRANSFORM = new AffineTransform();
/**
@@ -82,165 +87,26 @@ public class PSTextPainter extends Nativ
return g2d instanceof PSGraphics2D;
}
- /** {@inheritDoc} */
- protected void paintTextRun(TextRun textRun, Graphics2D g2d) throws IOException {
- AttributedCharacterIterator runaci = textRun.getACI();
- runaci.first();
-
- TextPaintInfo tpi = (TextPaintInfo)runaci.getAttribute(PAINT_INFO);
- if (tpi == null || !tpi.visible) {
- return;
- }
- if ((tpi != null) && (tpi.composite != null)) {
- g2d.setComposite(tpi.composite);
- }
-
- //------------------------------------
- TextSpanLayout layout = textRun.getLayout();
- logTextRun(runaci, layout);
- CharSequence chars = collectCharacters(runaci);
- runaci.first(); //Reset ACI
-
- final PSGraphics2D ps = (PSGraphics2D)g2d;
- final PSGenerator gen = ps.getPSGenerator();
+ @Override
+ protected void preparePainting(Graphics2D g2d) {
+ ps = (PSGraphics2D) g2d;
+ gen = ps.getPSGenerator();
ps.preparePainting();
+ }
- if (DEBUG) {
- log.debug("Text: " + chars);
- gen.commentln("%Text: " + chars);
- }
-
- GeneralPath debugShapes = null;
- if (DEBUG) {
- debugShapes = new GeneralPath();
- }
-
- TextUtil textUtil = new TextUtil(gen);
- textUtil.setupFonts(runaci);
- if (!textUtil.hasFonts()) {
- //Draw using Java2D when no native fonts are available
- textRun.getLayout().draw(g2d);
- return;
- }
-
+ @Override
+ protected void saveGraphicsState() throws IOException {
gen.saveGraphicsState();
- gen.concatMatrix(g2d.getTransform());
- Shape imclip = g2d.getClip();
- clip(ps, imclip);
-
- gen.writeln("BT"); //beginTextObject()
-
- AffineTransform localTransform = new AffineTransform();
- Point2D prevPos = null;
- GVTGlyphVector gv = layout.getGlyphVector();
- PSTextRun psRun = new PSTextRun(); //Used to split a text run into smaller runs
- for (int index = 0, c = gv.getNumGlyphs(); index < c; index++) {
- char ch = chars.charAt(index);
- boolean visibleChar = gv.isGlyphVisible(index)
- || (CharUtilities.isAnySpace(ch) && !CharUtilities.isZeroWidthSpace(ch));
- logCharacter(ch, layout, index, visibleChar);
- if (!visibleChar) {
- continue;
- }
- Point2D glyphPos = gv.getGlyphPosition(index);
-
- AffineTransform glyphTransform = gv.getGlyphTransform(index);
- if (log.isTraceEnabled()) {
- log.trace("pos " + glyphPos + ", transform " + glyphTransform);
- }
- if (DEBUG) {
- Shape sh = gv.getGlyphLogicalBounds(index);
- if (sh == null) {
- sh = new Ellipse2D.Double(glyphPos.getX(), glyphPos.getY(), 2, 2);
- }
- 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);
-
- boolean flushCurrentRun = false;
- //Try to optimize by combining characters using the same font and on the same line.
- if (glyphTransform != null) {
- //Happens for text-on-a-path
- flushCurrentRun = true;
- }
- if (psRun.getRunLength() >= 128) {
- //Don't let a run get too long
- flushCurrentRun = true;
- }
-
- //Note the position of the glyph relative to the previous one
- Point2D relPos;
- if (prevPos == null) {
- relPos = new Point2D.Double(0, 0);
- } else {
- relPos = new Point2D.Double(
- glyphPos.getX() - prevPos.getX(),
- glyphPos.getY() - prevPos.getY());
- }
- if (psRun.vertChanges == 0
- && psRun.getHorizRunLength() > 2
- && relPos.getY() != 0) {
- //new line
- flushCurrentRun = true;
- }
-
- //Select the actual character to paint
- char paintChar = (CharUtilities.isAnySpace(ch) ? ' ' : ch);
-
- //Select (sub)font for character
- Font f = textUtil.selectFontForChar(paintChar);
- char mapped = f.mapChar(ch);
- boolean fontChanging = textUtil.isFontChanging(f, mapped);
- if (fontChanging) {
- flushCurrentRun = true;
- }
-
- if (flushCurrentRun) {
- //Paint the current run and reset for the next run
- psRun.paint(ps, textUtil, tpi);
- psRun.reset();
- }
-
- //Track current run
- psRun.addCharacter(paintChar, relPos);
- psRun.noteStartingTransformation(localTransform);
-
- //Change font if necessary
- if (fontChanging) {
- textUtil.setCurrentFont(f, mapped);
- }
+ }
- //Update last position
- prevPos = glyphPos;
- }
- psRun.paint(ps, textUtil, tpi);
- gen.writeln("ET"); //endTextObject()
+ @Override
+ protected void restoreGraphicsState() throws IOException {
gen.restoreGraphicsState();
-
- if (DEBUG) {
- //Paint debug shapes
- g2d.setStroke(new BasicStroke(0));
- g2d.setColor(Color.LIGHT_GRAY);
- g2d.draw(debugShapes);
- }
}
- private void applyColor(Paint paint, final PSGenerator gen) throws IOException {
- if (paint == null) {
- return;
- } else if (paint instanceof Color) {
- Color col = (Color)paint;
- gen.useColor(col);
- } else {
- log.warn("Paint not supported: " + paint.toString());
- }
+ @Override
+ protected void setInitialTransform(AffineTransform transform) throws IOException {
+ gen.concatMatrix(transform);
}
private PSFontResource getResourceForFont(Font f, String postfix) {
@@ -248,7 +114,8 @@ public class PSTextPainter extends Nativ
return this.fontResources.getFontResourceForFontKey(key);
}
- private void clip(PSGraphics2D ps, Shape shape) throws IOException {
+ @Override
+ protected void clip(Shape shape) throws IOException {
if (shape == null) {
return;
}
@@ -258,17 +125,76 @@ public class PSTextPainter extends Nativ
ps.getPSGenerator().writeln("clip");
}
+ @Override
+ protected void beginTextObject() throws IOException {
+ gen.writeln("BT");
+ textUtil = new TextUtil();
+ psRun = new PSTextRun(); //Used to split a text run into smaller runs
+ }
+
+ @Override
+ protected void endTextObject() throws IOException {
+ psRun.paint(ps, textUtil, tpi);
+ gen.writeln("ET");
+ }
+
+ @Override
+ protected void positionGlyph(Point2D prevPos, Point2D glyphPos, boolean reposition) {
+ flushCurrentRun = false;
+ //Try to optimize by combining characters using the same font and on the same line.
+ if (reposition) {
+ //Happens for text-on-a-path
+ flushCurrentRun = true;
+ }
+ if (psRun.getRunLength() >= 128) {
+ //Don't let a run get too long
+ flushCurrentRun = true;
+ }
+
+ //Note the position of the glyph relative to the previous one
+ if (prevPos == null) {
+ relPos = new Point2D.Double(0, 0);
+ } else {
+ relPos = new Point2D.Double(
+ glyphPos.getX() - prevPos.getX(),
+ glyphPos.getY() - prevPos.getY());
+ }
+ if (psRun.vertChanges == 0
+ && psRun.getHorizRunLength() > 2
+ && relPos.getY() != 0) {
+ //new line
+ flushCurrentRun = true;
+ }
+ }
+
+ @Override
+ protected void writeGlyph(char glyph, AffineTransform localTransform) throws IOException {
+ boolean fontChanging = textUtil.isFontChanging(font, glyph);
+ if (fontChanging) {
+ flushCurrentRun = true;
+ }
+
+ if (flushCurrentRun) {
+ //Paint the current run and reset for the next run
+ psRun.paint(ps, textUtil, tpi);
+ psRun.reset();
+ }
+
+ //Track current run
+ psRun.addGlyph(glyph, relPos);
+ psRun.noteStartingTransformation(localTransform);
+
+ //Change font if necessary
+ if (fontChanging) {
+ textUtil.setCurrentFont(font, glyph);
+ }
+ }
+
private class TextUtil {
- private PSGenerator gen;
- private Font[] fonts;
private Font currentFont;
private int currentEncoding = -1;
- public TextUtil(PSGenerator gen) {
- this.gen = gen;
- }
-
public boolean isMultiByte(Font f) {
FontMetrics metrics = f.getFontMetrics();
boolean multiByte = metrics instanceof MultiByteFont || metrics instanceof LazyFont
@@ -276,15 +202,6 @@ public class PSTextPainter extends Nativ
return multiByte;
}
- public Font selectFontForChar(char ch) {
- for (int i = 0, c = fonts.length; i < c; i++) {
- if (fonts[i].hasChar(ch)) {
- return fonts[i];
- }
- }
- return fonts[0]; //TODO Maybe fall back to painting with shapes
- }
-
public void writeTextMatrix(AffineTransform transform) throws IOException {
double[] matrix = new double[6];
transform.getMatrix(matrix);
@@ -335,27 +252,19 @@ public class PSTextPainter extends Nativ
setCurrentFont(font, encoding);
}
- public void setupFonts(AttributedCharacterIterator runaci) {
- this.fonts = findFonts(runaci);
- }
-
- public boolean hasFonts() {
- return (fonts != null) && (fonts.length > 0);
- }
-
}
private class PSTextRun {
private AffineTransform textTransform;
- private List relativePositions = new java.util.LinkedList();
- private StringBuffer currentChars = new StringBuffer();
+ private List<Point2D> relativePositions = new LinkedList<Point2D>();
+ private StringBuffer currentGlyphs = new StringBuffer();
private int horizChanges = 0;
private int vertChanges = 0;
public void reset() {
textTransform = null;
- currentChars.setLength(0);
+ currentGlyphs.setLength(0);
horizChanges = 0;
vertChanges = 0;
relativePositions.clear();
@@ -369,9 +278,9 @@ public class PSTextPainter extends Nativ
return 0;
}
- public void addCharacter(char paintChar, Point2D relPos) {
+ public void addGlyph(char glyph, Point2D relPos) {
addRelativePosition(relPos);
- currentChars.append(paintChar);
+ currentGlyphs.append(glyph);
}
private void addRelativePosition(Point2D relPos) {
@@ -393,7 +302,7 @@ public class PSTextPainter extends Nativ
}
public int getRunLength() {
- return currentChars.length();
+ return currentGlyphs.length();
}
private boolean isXShow() {
@@ -407,9 +316,6 @@ public class PSTextPainter extends Nativ
public void paint(PSGraphics2D g2d, TextUtil textUtil, TextPaintInfo tpi)
throws IOException {
if (getRunLength() > 0) {
- if (log.isDebugEnabled()) {
- log.debug("Text run: " + currentChars);
- }
textUtil.writeTextMatrix(this.textTransform);
if (isXShow()) {
log.debug("Horizontal text: xshow");
@@ -431,25 +337,20 @@ public class PSTextPainter extends Nativ
private void paintXYShow(PSGraphics2D g2d, TextUtil textUtil, Paint paint,
boolean x, boolean y) throws IOException {
- PSGenerator gen = textUtil.gen;
- char firstChar = this.currentChars.charAt(0);
- //Font only has to be setup up before the first character
- Font f = textUtil.selectFontForChar(firstChar);
- char mapped = f.mapChar(firstChar);
- textUtil.selectFont(f, mapped);
- textUtil.setCurrentFont(f, mapped);
- applyColor(paint, gen);
+ char glyph = currentGlyphs.charAt(0);
+ textUtil.selectFont(font, glyph);
+ textUtil.setCurrentFont(font, glyph);
+ applyColor(paint);
- boolean multiByte = textUtil.isMultiByte(f);
+ boolean multiByte = textUtil.isMultiByte(font);
StringBuffer sb = new StringBuffer();
sb.append(multiByte ? '<' : '(');
- for (int i = 0, c = this.currentChars.length(); i < c; i++) {
- char ch = this.currentChars.charAt(i);
- mapped = f.mapChar(ch);
+ for (int i = 0, c = this.currentGlyphs.length(); i < c; i++) {
+ glyph = this.currentGlyphs.charAt(i);
if (multiByte) {
- sb.append(HexEncoder.encode(mapped));
+ sb.append(HexEncoder.encode(glyph));
} else {
- char codepoint = (char) (mapped % 256);
+ char codepoint = (char) (glyph % 256);
PSGenerator.escapeChar(codepoint, sb);
}
}
@@ -457,9 +358,9 @@ public class PSTextPainter extends Nativ
if (x || y) {
sb.append("\n[");
int idx = 0;
- Iterator iter = this.relativePositions.iterator();
+ Iterator<Point2D> iter = this.relativePositions.iterator();
while (iter.hasNext()) {
- Point2D pt = (Point2D)iter.next();
+ Point2D pt = iter.next();
if (idx > 0) {
if (x) {
sb.append(format(gen, pt.getX()));
@@ -500,6 +401,17 @@ public class PSTextPainter extends Nativ
gen.writeln(sb.toString());
}
+ private void applyColor(Paint paint) throws IOException {
+ if (paint == null) {
+ return;
+ } else if (paint instanceof Color) {
+ Color col = (Color) paint;
+ gen.useColor(col);
+ } else {
+ log.warn("Paint not supported: " + paint.toString());
+ }
+ }
+
private String format(PSGenerator gen, double coord) {
if (Math.abs(coord) < 0.00001) {
return "0";
@@ -510,30 +422,21 @@ public class PSTextPainter extends Nativ
private void paintStrokedGlyphs(PSGraphics2D g2d, TextUtil textUtil,
Paint strokePaint, Stroke stroke) throws IOException {
- PSGenerator gen = textUtil.gen;
-
- applyColor(strokePaint, gen);
+ applyColor(strokePaint);
PSGraphics2D.applyStroke(stroke, gen);
- Font f = null;
- Iterator iter = this.relativePositions.iterator();
+ Iterator<Point2D> iter = this.relativePositions.iterator();
iter.next();
Point2D pos = new Point2D.Double(0, 0);
gen.writeln("0 0 M");
- for (int i = 0, c = this.currentChars.length(); i < c; i++) {
- char ch = this.currentChars.charAt(0);
- if (i == 0) {
- //Font only has to be setup up before the first character
- f = textUtil.selectFontForChar(ch);
- }
- char mapped = f.mapChar(ch);
+ for (int i = 0, c = this.currentGlyphs.length(); i < c; i++) {
+ char mapped = this.currentGlyphs.charAt(i);
if (i == 0) {
- textUtil.selectFont(f, mapped);
- textUtil.setCurrentFont(f, mapped);
+ textUtil.selectFont(font, mapped);
+ textUtil.setCurrentFont(font, mapped);
}
//add glyph outlines to current path
- mapped = f.mapChar(this.currentChars.charAt(i));
- FontMetrics metrics = f.getFontMetrics();
+ FontMetrics metrics = font.getFontMetrics();
boolean multiByte = metrics instanceof MultiByteFont
|| metrics instanceof LazyFont
&& ((LazyFont) metrics).getRealFont() instanceof MultiByteFont;
@@ -542,14 +445,14 @@ public class PSTextPainter extends Nativ
gen.write(HexEncoder.encode(mapped));
gen.write(">");
} else {
- char codepoint = (char)(mapped % 256);
+ char codepoint = (char) (mapped % 256);
gen.write("(" + codepoint + ")");
}
gen.writeln(" false charpath");
if (iter.hasNext()) {
//Position for the next character
- Point2D pt = (Point2D)iter.next();
+ Point2D pt = iter.next();
pos.setLocation(pos.getX() + pt.getX(), pos.getY() - pt.getY());
gen.writeln(gen.formatDouble5(pos.getX()) + " "
+ gen.formatDouble5(pos.getY()) + " M");
Modified: xmlgraphics/fop/branches/Temp_FopFontsForSVG/src/java/org/apache/fop/svg/ACIUtils.java
URL: http://svn.apache.org/viewvc/xmlgraphics/fop/branches/Temp_FopFontsForSVG/src/java/org/apache/fop/svg/ACIUtils.java?rev=1508208&r1=1508207&r2=1508208&view=diff
==============================================================================
--- xmlgraphics/fop/branches/Temp_FopFontsForSVG/src/java/org/apache/fop/svg/ACIUtils.java (original)
+++ xmlgraphics/fop/branches/Temp_FopFontsForSVG/src/java/org/apache/fop/svg/ACIUtils.java Mon Jul 29 21:45:20 2013
@@ -38,7 +38,8 @@ import org.apache.batik.gvt.text.GVTAttr
import org.apache.fop.fonts.Font;
import org.apache.fop.fonts.FontInfo;
-import org.apache.fop.fonts.FontTriplet;
+import org.apache.fop.svg.font.FOPGVTFont;
+import org.apache.fop.svg.font.FOPGVTFontFamily;
/**
* Utilities for java.text.AttributedCharacterIterator.
@@ -64,57 +65,43 @@ public final class ACIUtils {
@SuppressWarnings("unchecked")
List<GVTFontFamily> gvtFonts = (List<GVTFontFamily>) aci.getAttribute(
GVTAttributedCharacterIterator.TextAttribute.GVT_FONT_FAMILIES);
- Float posture = (Float) aci.getAttribute(TextAttribute.POSTURE);
- Float taWeight = (Float) aci.getAttribute(TextAttribute.WEIGHT);
- Float fontSize = (Float) aci.getAttribute(TextAttribute.SIZE);
-
- String style = toStyle(posture);
- int weight = toCSSWeight(taWeight);
- int fsize = (int)(fontSize.floatValue() * 1000);
+ String style = toStyle((Float) aci.getAttribute(TextAttribute.POSTURE));
+ int weight = toCSSWeight((Float) aci.getAttribute(TextAttribute.WEIGHT));
+ float fontSize = ((Float) aci.getAttribute(TextAttribute.SIZE)).floatValue();
String firstFontFamily = null;
-
//GVT_FONT can sometimes be different from the fonts in GVT_FONT_FAMILIES
//or GVT_FONT_FAMILIES can even be empty and only GVT_FONT is set
- /* The following code section is not available until Batik 1.7 is released. */
- GVTFont gvtFont = (GVTFont)aci.getAttribute(
- GVTAttributedCharacterIterator.TextAttribute.GVT_FONT);
+ GVTFont gvtFont = (GVTFont) aci.getAttribute(GVTAttributedCharacterIterator.TextAttribute.GVT_FONT);
if (gvtFont != null) {
String gvtFontFamily = gvtFont.getFamilyName();
- if (fontInfo.hasFont(gvtFontFamily, style, weight)) {
- FontTriplet triplet = fontInfo.fontLookup(gvtFontFamily, style,
- weight);
- Font f = fontInfo.getFontInstance(triplet, fsize);
+ if (gvtFont instanceof FOPGVTFont) {
+ Font font = ((FOPGVTFont) gvtFont).getFont();
if (LOG.isDebugEnabled()) {
LOG.debug("Found a font that matches the GVT font: "
+ gvtFontFamily + ", " + weight + ", " + style
- + " -> " + f);
+ + " -> " + font);
}
- fonts.add(f);
+ fonts.add(font);
}
firstFontFamily = gvtFontFamily;
}
if (gvtFonts != null) {
boolean haveInstanceOfSVGFontFamily = false;
- for (GVTFontFamily fam : gvtFonts) {
- if (fam instanceof SVGFontFamily) {
+ for (GVTFontFamily fontFamily : gvtFonts) {
+ if (fontFamily instanceof SVGFontFamily) {
haveInstanceOfSVGFontFamily = true;
- }
- String fontFamily = fam.getFamilyName();
- if (fontInfo.hasFont(fontFamily, style, weight)) {
- FontTriplet triplet = fontInfo.fontLookup(fontFamily, style,
- weight);
- Font f = fontInfo.getFontInstance(triplet, fsize);
+ } else if (fontFamily instanceof FOPGVTFontFamily) {
+ Font font = ((FOPGVTFontFamily) fontFamily).deriveFont(fontSize, aci).getFont();
if (LOG.isDebugEnabled()) {
LOG.debug("Found a font that matches the GVT font family: "
- + fontFamily + ", " + weight + ", " + style
- + " -> " + f);
+ + fontFamily.getFamilyName() + ", " + weight + ", " + style + " -> " + font);
}
- fonts.add(f);
+ fonts.add(font);
}
if (firstFontFamily == null) {
- firstFontFamily = fontFamily;
+ firstFontFamily = fontFamily.getFamilyName();
}
}
// SVG fonts are embedded fonts in the SVG document and are rarely used; however if they
@@ -126,25 +113,10 @@ public final class ACIUtils {
return null; // Let Batik paint this text!
}
}
- if (fonts.isEmpty()) {
- if (firstFontFamily == null) {
- //This will probably never happen. Just to be on the safe side.
- firstFontFamily = "any";
- }
- //lookup with fallback possibility (incl. substitution notification)
- FontTriplet triplet = fontInfo.fontLookup(firstFontFamily, style, weight);
- Font f = fontInfo.getFontInstance(triplet, fsize);
- if (LOG.isDebugEnabled()) {
- LOG.debug("Falling back to adjustable font lookup up for: "
- + firstFontFamily + ", " + weight + ", " + style
- + " -> " + f);
- }
- fonts.add(f);
- }
- return fonts.toArray(new Font[fonts.size()]);
+ return fonts.isEmpty() ? null : fonts.toArray(new Font[fonts.size()]);
}
- private static int toCSSWeight(Float weight) {
+ public static int toCSSWeight(Float weight) {
if (weight == null) {
return 400;
} else if (weight <= TextAttribute.WEIGHT_EXTRA_LIGHT.floatValue()) {
@@ -170,7 +142,7 @@ public final class ACIUtils {
}
}
- private static String toStyle(Float posture) {
+ public static String toStyle(Float posture) {
return ((posture != null) && (posture.floatValue() > 0.0))
? Font.STYLE_ITALIC
: Font.STYLE_NORMAL;
Modified: xmlgraphics/fop/branches/Temp_FopFontsForSVG/src/java/org/apache/fop/svg/AbstractFOPTextPainter.java
URL: http://svn.apache.org/viewvc/xmlgraphics/fop/branches/Temp_FopFontsForSVG/src/java/org/apache/fop/svg/AbstractFOPTextPainter.java?rev=1508208&r1=1508207&r2=1508208&view=diff
==============================================================================
--- xmlgraphics/fop/branches/Temp_FopFontsForSVG/src/java/org/apache/fop/svg/AbstractFOPTextPainter.java (original)
+++ xmlgraphics/fop/branches/Temp_FopFontsForSVG/src/java/org/apache/fop/svg/AbstractFOPTextPainter.java Mon Jul 29 21:45:20 2013
@@ -23,20 +23,15 @@ import java.awt.Color;
import java.awt.Graphics2D;
import java.awt.Paint;
import java.awt.Shape;
-import java.awt.font.TextAttribute;
-import java.awt.geom.AffineTransform;
import java.awt.geom.Point2D;
import java.awt.geom.Rectangle2D;
import java.io.IOException;
import java.text.AttributedCharacterIterator;
import java.text.CharacterIterator;
-import java.util.Iterator;
-import java.util.List;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
-import org.apache.batik.dom.svg.SVGOMTextElement;
import org.apache.batik.gvt.TextNode;
import org.apache.batik.gvt.TextPainter;
import org.apache.batik.gvt.renderer.StrokingTextPainter;
@@ -66,15 +61,15 @@ public abstract class AbstractFOPTextPai
* Use the stroking text painter to get the bounds and shape.
* Also used as a fallback to draw the string with strokes.
*/
- protected static final TextPainter
- PROXY_PAINTER = StrokingTextPainter.getInstance();
+ private final TextPainter proxyTextPainter;
/**
* Create a new PS text painter with the given font information.
* @param nativeTextHandler the NativeTextHandler instance used for text painting
*/
- public AbstractFOPTextPainter(FOPTextHandler nativeTextHandler) {
+ public AbstractFOPTextPainter(FOPTextHandler nativeTextHandler, TextPainter proxyTextPainter) {
this.nativeTextHandler = nativeTextHandler;
+ this.proxyTextPainter = proxyTextPainter;
}
/**
@@ -85,19 +80,10 @@ public abstract class AbstractFOPTextPai
* @param g2d the Graphics2D to use
*/
public void paint(TextNode node, Graphics2D g2d) {
- Point2D loc = node.getLocation();
- if (!isSupportedGraphics2D(g2d) || hasUnsupportedAttributes(node)) {
- if (log.isDebugEnabled()) {
- log.debug("painting text node " + node
- + " by stroking due to unsupported attributes or an incompatible Graphics2D");
- }
- PROXY_PAINTER.paint(node, g2d);
- } else {
- if (log.isDebugEnabled()) {
- log.debug("painting text node " + node + " normally.");
- }
- paintTextRuns(node.getTextRuns(), g2d, loc);
+ if (isSupportedGraphics2D(g2d)) {
+ new TextRunPainter().paintTextRuns(node.getTextRuns(), g2d, node.getLocation());
}
+ proxyTextPainter.paint(node, g2d);
}
/**
@@ -109,190 +95,99 @@ public abstract class AbstractFOPTextPai
*/
protected abstract boolean isSupportedGraphics2D(Graphics2D g2d);
- private boolean hasUnsupportedAttributes(TextNode node) {
- Iterator iter = node.getTextRuns().iterator();
- while (iter.hasNext()) {
- StrokingTextPainter.TextRun
- run = (StrokingTextPainter.TextRun)iter.next();
- AttributedCharacterIterator aci = run.getACI();
- boolean hasUnsupported = hasUnsupportedAttributes(aci);
- if (hasUnsupported) {
- return true;
- }
- }
- return false;
- }
-
- private boolean hasUnsupportedAttributes(AttributedCharacterIterator aci) {
- boolean hasUnsupported = false;
+ private class TextRunPainter {
- Font font = getFont(aci);
- String text = getText(aci);
- if (hasUnsupportedGlyphs(text, font)) {
- log.trace("-> Unsupported glyphs found");
- hasUnsupported = true;
- }
+ private Point2D currentLocation;
- TextPaintInfo tpi = (TextPaintInfo) aci.getAttribute(
- GVTAttributedCharacterIterator.TextAttribute.PAINT_INFO);
- if ((tpi != null)
- && ((tpi.strokeStroke != null && tpi.strokePaint != null)
- || (tpi.strikethroughStroke != null)
- || (tpi.underlineStroke != null)
- || (tpi.overlineStroke != null))) {
- log.trace("-> under/overlines etc. found");
- hasUnsupported = true;
- }
-
- //Alpha is not supported
- Paint foreground = (Paint) aci.getAttribute(TextAttribute.FOREGROUND);
- if (foreground instanceof Color) {
- Color col = (Color)foreground;
- if (col.getAlpha() != 255) {
- log.trace("-> transparency found");
- hasUnsupported = true;
+ public void paintTextRuns(Iterable<StrokingTextPainter.TextRun> textRuns, Graphics2D g2d,
+ Point2D nodeLocation) {
+ currentLocation = new Point2D.Double(nodeLocation.getX(), nodeLocation.getY());
+ for (StrokingTextPainter.TextRun run : textRuns) {
+ paintTextRun(run, g2d);
}
}
- Object letSpace = aci.getAttribute(
- GVTAttributedCharacterIterator.TextAttribute.LETTER_SPACING);
- if (letSpace != null) {
- log.trace("-> letter spacing found");
- hasUnsupported = true;
- }
-
- Object wordSpace = aci.getAttribute(
- GVTAttributedCharacterIterator.TextAttribute.WORD_SPACING);
- if (wordSpace != null) {
- log.trace("-> word spacing found");
- hasUnsupported = true;
- }
-
- Object lengthAdjust = aci.getAttribute(
- GVTAttributedCharacterIterator.TextAttribute.LENGTH_ADJUST);
- if (lengthAdjust != null) {
- log.trace("-> length adjustments found");
- hasUnsupported = true;
- }
-
- Object writeMod = aci.getAttribute(
- GVTAttributedCharacterIterator.TextAttribute.WRITING_MODE);
- if (writeMod != null
- && !GVTAttributedCharacterIterator.TextAttribute.WRITING_MODE_LTR.equals(
- writeMod)) {
- log.trace("-> Unsupported writing modes found");
- hasUnsupported = true;
- }
-
- Object vertOr = aci.getAttribute(
- GVTAttributedCharacterIterator.TextAttribute.VERTICAL_ORIENTATION);
- if (GVTAttributedCharacterIterator.TextAttribute.ORIENTATION_ANGLE.equals(
- vertOr)) {
- log.trace("-> vertical orientation found");
- hasUnsupported = true;
- }
-
- Object rcDel = aci.getAttribute(
- GVTAttributedCharacterIterator.TextAttribute.TEXT_COMPOUND_DELIMITER);
- //Batik 1.6 returns null here which makes it impossible to determine whether this can
- //be painted or not, i.e. fall back to stroking. :-(
- if (rcDel != null && !(rcDel instanceof SVGOMTextElement)) {
- log.trace("-> spans found");
- hasUnsupported = true; //Filter spans
- }
-
- if (hasUnsupported) {
- log.trace("Unsupported attributes found in ACI, using StrokingTextPainter");
- }
- return hasUnsupported;
- }
-
- /**
- * Paint a list of text runs on the Graphics2D at a given location.
- * @param textRuns the list of text runs
- * @param g2d the Graphics2D to paint to
- * @param loc the current location of the "cursor"
- */
- protected void paintTextRuns(List textRuns, Graphics2D g2d, Point2D loc) {
- Point2D currentloc = loc;
- Iterator i = textRuns.iterator();
- while (i.hasNext()) {
- StrokingTextPainter.TextRun
- run = (StrokingTextPainter.TextRun)i.next();
- currentloc = paintTextRun(run, g2d, currentloc);
- }
- }
-
- /**
- * Paint a single text run on the Graphics2D at a given location.
- * @param run the text run to paint
- * @param g2d the Graphics2D to paint to
- * @param loc the current location of the "cursor"
- * @return the new location of the "cursor" after painting the text run
- */
- protected Point2D paintTextRun(StrokingTextPainter.TextRun run, Graphics2D g2d, Point2D loc) {
- AttributedCharacterIterator aci = run.getACI();
- aci.first();
-
- updateLocationFromACI(aci, loc);
- AffineTransform at = g2d.getTransform();
- loc = at.transform(loc, null);
-
- // font
- Font font = getFont(aci);
- if (font != null) {
- nativeTextHandler.setOverrideFont(font);
- }
-
- // color
- TextPaintInfo tpi = (TextPaintInfo) aci.getAttribute(
- GVTAttributedCharacterIterator.TextAttribute.PAINT_INFO);
- if (tpi == null) {
- return loc;
- }
- Paint foreground = tpi.fillPaint;
- if (foreground instanceof Color) {
- Color col = (Color)foreground;
- g2d.setColor(col);
- }
- g2d.setPaint(foreground);
-
- // text anchor
- TextNode.Anchor anchor = (TextNode.Anchor)aci.getAttribute(
- GVTAttributedCharacterIterator.TextAttribute.ANCHOR_TYPE);
-
- // text
- String txt = getText(aci);
- float advance = getStringWidth(txt, font);
- float tx = 0;
- if (anchor != null) {
- switch (anchor.getType()) {
- case TextNode.Anchor.ANCHOR_MIDDLE:
- tx = -advance / 2;
- break;
- case TextNode.Anchor.ANCHOR_END:
- tx = -advance;
- break;
- default: //nop
+ private void paintTextRun(StrokingTextPainter.TextRun run, Graphics2D g2d) {
+ AttributedCharacterIterator aci = run.getACI();
+ aci.first();
+ updateLocationFromACI(aci, currentLocation);
+ // font
+ Font font = getFont(aci);
+ if (font != null) {
+ nativeTextHandler.setOverrideFont(font);
}
- }
-
- // draw string
- double x = loc.getX();
- double y = loc.getY();
- try {
+ // color
+ TextPaintInfo tpi = (TextPaintInfo) aci.getAttribute(
+ GVTAttributedCharacterIterator.TextAttribute.PAINT_INFO);
+ if (tpi == null) {
+ return;
+ }
+ Paint foreground = tpi.fillPaint;
+ if (foreground instanceof Color) {
+ Color col = (Color) foreground;
+ g2d.setColor(col);
+ }
+ g2d.setPaint(foreground);
+ // text anchor
+ TextNode.Anchor anchor = (TextNode.Anchor) aci.getAttribute(
+ GVTAttributedCharacterIterator.TextAttribute.ANCHOR_TYPE);
+ // text
+ String txt = getText(aci);
+ double advance = font == null ? run.getLayout().getAdvance2D().getX() : getStringWidth(txt, font);
+ double tx = 0;
+ if (anchor != null) {
+ switch (anchor.getType()) {
+ case TextNode.Anchor.ANCHOR_MIDDLE:
+ tx = -advance / 2;
+ break;
+ case TextNode.Anchor.ANCHOR_END:
+ tx = -advance;
+ break;
+ default: //nop
+ }
+ }
+ // draw string
+ Point2D outputLocation = g2d.getTransform().transform(currentLocation, null);
+ double x = outputLocation.getX();
+ double y = outputLocation.getY();
try {
- nativeTextHandler.drawString(g2d, txt, (float)x + tx, (float)y);
- } catch (IOException ioe) {
- if (g2d instanceof AFPGraphics2D) {
- ((AFPGraphics2D)g2d).handleIOException(ioe);
+ try {
+ //TODO draw underline and overline if set
+ nativeTextHandler.drawString(g2d, txt, (float) (x + tx), (float) y);
+ //TODO draw strikethrough if set
+ } catch (IOException ioe) {
+ if (g2d instanceof AFPGraphics2D) {
+ ((AFPGraphics2D) g2d).handleIOException(ioe);
+ }
}
+ } finally {
+ nativeTextHandler.setOverrideFont(null);
+ }
+ currentLocation.setLocation(currentLocation.getX() + advance, currentLocation.getY());
+ }
+ private void updateLocationFromACI(AttributedCharacterIterator aci, Point2D loc) {
+ //Adjust position of span
+ Float xpos = (Float) aci.getAttribute(
+ GVTAttributedCharacterIterator.TextAttribute.X);
+ Float ypos = (Float) aci.getAttribute(
+ GVTAttributedCharacterIterator.TextAttribute.Y);
+ Float dxpos = (Float) aci.getAttribute(
+ GVTAttributedCharacterIterator.TextAttribute.DX);
+ Float dypos = (Float) aci.getAttribute(
+ GVTAttributedCharacterIterator.TextAttribute.DY);
+ if (xpos != null) {
+ loc.setLocation(xpos.doubleValue(), loc.getY());
+ }
+ if (ypos != null) {
+ loc.setLocation(loc.getX(), ypos.doubleValue());
+ }
+ if (dxpos != null) {
+ loc.setLocation(loc.getX() + dxpos.doubleValue(), loc.getY());
+ }
+ if (dypos != null) {
+ loc.setLocation(loc.getX(), loc.getY() + dypos.doubleValue());
}
- } finally {
- nativeTextHandler.setOverrideFont(null);
}
- loc.setLocation(loc.getX() + advance, loc.getY());
- return loc;
}
/**
@@ -305,36 +200,9 @@ public abstract class AbstractFOPTextPai
for (char c = aci.first(); c != CharacterIterator.DONE; c = aci.next()) {
sb.append(c);
}
- aci.first();
return sb.toString();
}
- private void updateLocationFromACI(
- AttributedCharacterIterator aci,
- Point2D loc) {
- //Adjust position of span
- Float xpos = (Float)aci.getAttribute(
- GVTAttributedCharacterIterator.TextAttribute.X);
- Float ypos = (Float)aci.getAttribute(
- GVTAttributedCharacterIterator.TextAttribute.Y);
- Float dxpos = (Float)aci.getAttribute(
- GVTAttributedCharacterIterator.TextAttribute.DX);
- Float dypos = (Float)aci.getAttribute(
- GVTAttributedCharacterIterator.TextAttribute.DY);
- if (xpos != null) {
- loc.setLocation(xpos.doubleValue(), loc.getY());
- }
- if (ypos != null) {
- loc.setLocation(loc.getX(), ypos.doubleValue());
- }
- if (dxpos != null) {
- loc.setLocation(loc.getX() + dxpos.doubleValue(), loc.getY());
- }
- if (dypos != null) {
- loc.setLocation(loc.getX(), loc.getY() + dypos.doubleValue());
- }
- }
-
private Font getFont(AttributedCharacterIterator aci) {
Font[] fonts = ACIUtils.findFontsForBatikACI(aci, nativeTextHandler.getFontInfo());
return fonts == null ? null : fonts[0];
@@ -360,21 +228,6 @@ public abstract class AbstractFOPTextPai
return wordWidth / 1000f;
}
- private boolean hasUnsupportedGlyphs(String str, Font font) {
- if (font == null) {
- return true;
- }
- for (int i = 0; i < str.length(); i++) {
- char c = str.charAt(i);
- if (!((c == ' ') || (c == '\n') || (c == '\r') || (c == '\t'))) {
- if (!font.hasChar(c)) {
- return true;
- }
- }
- }
- return false;
- }
-
/**
* Get the outline shape of the text characters.
* This uses the StrokingTextPainter to get the outline
@@ -384,7 +237,7 @@ public abstract class AbstractFOPTextPai
* @return the outline shape of the text characters
*/
public Shape getOutline(TextNode node) {
- return PROXY_PAINTER.getOutline(node);
+ return proxyTextPainter.getOutline(node);
}
/**
@@ -399,7 +252,7 @@ public abstract class AbstractFOPTextPai
/* (todo) getBounds2D() is too slow
* because it uses the StrokingTextPainter. We should implement this
* method ourselves. */
- return PROXY_PAINTER.getBounds2D(node);
+ return proxyTextPainter.getBounds2D(node);
}
/**
@@ -411,7 +264,7 @@ public abstract class AbstractFOPTextPai
* @return the bounds of the text
*/
public Rectangle2D getGeometryBounds(TextNode node) {
- return PROXY_PAINTER.getGeometryBounds(node);
+ return proxyTextPainter.getGeometryBounds(node);
}
// Methods that have no purpose for PS
Modified: xmlgraphics/fop/branches/Temp_FopFontsForSVG/src/java/org/apache/fop/svg/AbstractFOPTranscoder.java
URL: http://svn.apache.org/viewvc/xmlgraphics/fop/branches/Temp_FopFontsForSVG/src/java/org/apache/fop/svg/AbstractFOPTranscoder.java?rev=1508208&r1=1508207&r2=1508208&view=diff
==============================================================================
--- xmlgraphics/fop/branches/Temp_FopFontsForSVG/src/java/org/apache/fop/svg/AbstractFOPTranscoder.java (original)
+++ xmlgraphics/fop/branches/Temp_FopFontsForSVG/src/java/org/apache/fop/svg/AbstractFOPTranscoder.java Mon Jul 29 21:45:20 2013
@@ -36,9 +36,9 @@ import org.apache.avalon.framework.confi
import org.apache.commons.logging.Log;
import org.apache.commons.logging.impl.SimpleLog;
-import org.apache.batik.bridge.UserAgent;
import org.apache.batik.dom.svg.SVGDOMImplementation;
import org.apache.batik.dom.util.DocumentFactory;
+import org.apache.batik.gvt.font.FontFamilyResolver;
import org.apache.batik.transcoder.ErrorHandler;
import org.apache.batik.transcoder.SVGAbstractTranscoder;
import org.apache.batik.transcoder.TranscoderException;
@@ -56,6 +56,8 @@ import org.apache.xmlgraphics.image.load
import org.apache.xmlgraphics.image.loader.impl.AbstractImageSessionContext;
import org.apache.xmlgraphics.util.UnitConv;
+import org.apache.fop.svg.font.FOPFontFamilyResolver;
+
/**
* This is the common base class of all of FOP's transcoders.
*/
@@ -86,11 +88,6 @@ public abstract class AbstractFOPTransco
/** The value to turn off text stroking. */
public static final Boolean VALUE_FORMAT_OFF = Boolean.FALSE;
- /**
- * The user agent dedicated to this Transcoder.
- */
- protected UserAgent userAgent = createUserAgent();
-
private Log logger;
private EntityResolver resolver;
private Configuration cfg = null;
@@ -113,7 +110,7 @@ public abstract class AbstractFOPTransco
* this method if you need non-default behaviour.
* @return UserAgent the newly created user agent
*/
- protected UserAgent createUserAgent() {
+ protected FOPTranscoderUserAgent createUserAgent() {
return new FOPTranscoderUserAgent();
}
@@ -331,6 +328,8 @@ public abstract class AbstractFOPTransco
*/
protected class FOPTranscoderUserAgent extends SVGAbstractTranscoderUserAgent {
+ private FOPFontFamilyResolver fontFamilyResolver;
+
/**
* Displays the specified error message using the {@link ErrorHandler}.
* @param message the message to display
@@ -386,6 +385,15 @@ public abstract class AbstractFOPTransco
return "print";
}
+ public void setFontFamilyResolver(FOPFontFamilyResolver resolver) {
+ fontFamilyResolver = resolver;
+ }
+
+ @Override
+ public FontFamilyResolver getFontFamilyResolver() {
+ return fontFamilyResolver;
+ }
+
}
}
Modified: xmlgraphics/fop/branches/Temp_FopFontsForSVG/src/java/org/apache/fop/svg/NativeTextPainter.java
URL: http://svn.apache.org/viewvc/xmlgraphics/fop/branches/Temp_FopFontsForSVG/src/java/org/apache/fop/svg/NativeTextPainter.java?rev=1508208&r1=1508207&r2=1508208&view=diff
==============================================================================
--- xmlgraphics/fop/branches/Temp_FopFontsForSVG/src/java/org/apache/fop/svg/NativeTextPainter.java (original)
+++ xmlgraphics/fop/branches/Temp_FopFontsForSVG/src/java/org/apache/fop/svg/NativeTextPainter.java Mon Jul 29 21:45:20 2013
@@ -19,7 +19,14 @@
package org.apache.fop.svg;
+import java.awt.BasicStroke;
+import java.awt.Color;
import java.awt.Graphics2D;
+import java.awt.Shape;
+import java.awt.geom.AffineTransform;
+import java.awt.geom.Ellipse2D;
+import java.awt.geom.GeneralPath;
+import java.awt.geom.Point2D;
import java.io.IOException;
import java.text.AttributedCharacterIterator;
import java.util.List;
@@ -27,11 +34,17 @@ import java.util.List;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
+import org.apache.batik.bridge.SVGGVTFont;
+import org.apache.batik.gvt.font.FontFamilyResolver;
+import org.apache.batik.gvt.font.GVTGlyphVector;
import org.apache.batik.gvt.renderer.StrokingTextPainter;
+import org.apache.batik.gvt.text.TextPaintInfo;
import org.apache.batik.gvt.text.TextSpanLayout;
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.util.CharUtilities;
/**
@@ -41,17 +54,26 @@ import org.apache.fop.util.CharUtilities
public abstract class NativeTextPainter extends StrokingTextPainter {
/** the logger for this class */
- protected Log log = LogFactory.getLog(NativeTextPainter.class);
+ protected static final Log log = LogFactory.getLog(NativeTextPainter.class);
+
+ private static final boolean DEBUG = false;
/** the font collection */
protected final FontInfo fontInfo;
+ protected final FontFamilyResolver fontFamilyResolver;
+
+ protected Font font;
+
+ protected TextPaintInfo tpi;
+
/**
* Creates a new instance.
* @param fontInfo the font collection
*/
public NativeTextPainter(FontInfo fontInfo) {
this.fontInfo = fontInfo;
+ this.fontFamilyResolver = new FOPFontFamilyResolverImpl(fontInfo);
}
/**
@@ -68,11 +90,93 @@ public abstract class NativeTextPainter
* @param g2d the target Graphics2D instance
* @throws IOException if an I/O error occurs while rendering the text
*/
- protected abstract void paintTextRun(TextRun textRun, Graphics2D g2d) throws IOException;
+ protected final void paintTextRun(TextRun textRun, Graphics2D g2d) throws IOException {
+ AttributedCharacterIterator runaci = textRun.getACI();
+ runaci.first();
+
+ tpi = (TextPaintInfo) runaci.getAttribute(PAINT_INFO);
+ if (tpi == null || !tpi.visible) {
+ return;
+ }
+ 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;
+ }
+ font = ((FOPGVTFont) gv.getFont()).getFont();
+
+ saveGraphicsState();
+ setInitialTransform(g2d.getTransform());
+ clip(g2d.getClip());
+ beginTextObject();
+
+ AffineTransform localTransform = new AffineTransform();
+ Point2D prevPos = null;
+ AffineTransform prevGlyphTransform = null;
+ for (int index = 0, c = gv.getNumGlyphs(); index < c; index++) {
+ if (!gv.isGlyphVisible(index)) {
+ continue;
+ }
+ Point2D glyphPos = gv.getGlyphPosition(index);
+
+ AffineTransform glyphTransform = gv.getGlyphTransform(index);
+ if (log.isTraceEnabled()) {
+ log.trace("pos " + glyphPos + ", transform " + glyphTransform);
+ }
+ if (DEBUG) {
+ Shape sh = gv.getGlyphLogicalBounds(index);
+ if (sh == null) {
+ sh = new Ellipse2D.Double(glyphPos.getX(), glyphPos.getY(), 2, 2);
+ }
+ 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);
+ }
+ endTextObject();
+ restoreGraphicsState();
+ if (DEBUG) {
+ //Paint debug shapes
+ g2d.setStroke(new BasicStroke(0));
+ g2d.setColor(Color.LIGHT_GRAY);
+ g2d.draw(debugShapes);
+ }
+ }
- /** {@inheritDoc} */
@Override
- protected void paintTextRuns(List textRuns, Graphics2D g2d) {
+ protected void paintTextRuns(@SuppressWarnings("rawtypes") List textRuns, Graphics2D g2d) {
if (log.isTraceEnabled()) {
log.trace("paintTextRuns: count = " + textRuns.size());
}
@@ -81,7 +185,7 @@ public abstract class NativeTextPainter
return;
}
for (int i = 0; i < textRuns.size(); i++) {
- TextRun textRun = (TextRun)textRuns.get(i);
+ TextRun textRun = (TextRun) textRuns.get(i);
try {
paintTextRun(textRun, g2d);
} catch (IOException ioe) {
@@ -92,16 +196,6 @@ public abstract class NativeTextPainter
}
/**
- * Finds an array of suitable fonts for a given AttributedCharacterIterator.
- * @param aci the character iterator
- * @return the array of fonts
- */
- protected Font[] findFonts(AttributedCharacterIterator aci) {
- Font[] fonts = ACIUtils.findFontsForBatikACI(aci, fontInfo);
- return fonts;
- }
-
- /**
* Collects all characters from an {@link AttributedCharacterIterator}.
* @param runaci the character iterator
* @return the characters
@@ -115,6 +209,25 @@ public abstract class NativeTextPainter
return chars;
}
+ protected abstract void preparePainting(Graphics2D g2d);
+
+ protected abstract void saveGraphicsState() throws IOException;
+
+ protected abstract void restoreGraphicsState() throws IOException;
+
+ protected abstract void setInitialTransform(AffineTransform transform) throws IOException;
+
+ protected abstract void clip(Shape clip) throws IOException;
+
+ protected abstract void beginTextObject() throws IOException;
+
+ protected abstract void endTextObject() throws IOException;
+
+ protected abstract void positionGlyph(Point2D prevPos, Point2D glyphPos, boolean reposition);
+
+ protected abstract void writeGlyph(char glyph, AffineTransform transform) throws IOException;
+
+
/**
* @param runaci an attributed character iterator
* @param layout a text span layout
@@ -155,5 +268,9 @@ public abstract class NativeTextPainter
}
}
+ @Override
+ protected FontFamilyResolver getFontFamilyResolver() {
+ return this.fontFamilyResolver;
+ }
}
Modified: xmlgraphics/fop/branches/Temp_FopFontsForSVG/src/java/org/apache/fop/svg/PDFTextPainter.java
URL: http://svn.apache.org/viewvc/xmlgraphics/fop/branches/Temp_FopFontsForSVG/src/java/org/apache/fop/svg/PDFTextPainter.java?rev=1508208&r1=1508207&r2=1508208&view=diff
==============================================================================
--- xmlgraphics/fop/branches/Temp_FopFontsForSVG/src/java/org/apache/fop/svg/PDFTextPainter.java (original)
+++ xmlgraphics/fop/branches/Temp_FopFontsForSVG/src/java/org/apache/fop/svg/PDFTextPainter.java Mon Jul 29 21:45:20 2013
@@ -19,25 +19,17 @@
package org.apache.fop.svg;
-import java.awt.BasicStroke;
import java.awt.Color;
import java.awt.Graphics2D;
import java.awt.Paint;
import java.awt.Shape;
import java.awt.Stroke;
import java.awt.geom.AffineTransform;
-import java.awt.geom.Ellipse2D;
-import java.awt.geom.GeneralPath;
import java.awt.geom.Point2D;
-import java.text.AttributedCharacterIterator;
-import org.apache.batik.gvt.font.GVTGlyphVector;
import org.apache.batik.gvt.text.TextPaintInfo;
-import org.apache.batik.gvt.text.TextSpanLayout;
-import org.apache.fop.fonts.Font;
import org.apache.fop.fonts.FontInfo;
-import org.apache.fop.util.CharUtilities;
/**
* Renders the attributed character iterator of a {@link org.apache.batik.gvt.TextNode}.
@@ -51,11 +43,19 @@ import org.apache.fop.util.CharUtilities
*/
class PDFTextPainter extends NativeTextPainter {
- private static final boolean DEBUG = false;
+ private PDFGraphics2D pdf;
+
+ private PDFTextUtil textUtil;
+
+ private double prevVisibleGlyphWidth;
+
+ private boolean repositionNextGlyph;
/**
* Create a new PDF text painter with the given font information.
+ *
* @param fi the font info
+ * @param fontFamilyResolver the Font Family Resolver
*/
public PDFTextPainter(FontInfo fi) {
super(fi);
@@ -67,29 +67,29 @@ class PDFTextPainter extends NativeTextP
return g2d instanceof PDFGraphics2D;
}
- /** {@inheritDoc} */
@Override
- protected void paintTextRun(TextRun textRun, Graphics2D g2d) {
- AttributedCharacterIterator runaci = textRun.getACI();
- runaci.first();
+ protected void preparePainting(Graphics2D g2d) {
+ pdf = (PDFGraphics2D) g2d;
+ }
- TextPaintInfo tpi = (TextPaintInfo)runaci.getAttribute(PAINT_INFO);
- if (tpi == null || !tpi.visible) {
- return;
- }
- if ((tpi != null) && (tpi.composite != null)) {
- g2d.setComposite(tpi.composite);
- }
+ @Override
+ protected void saveGraphicsState() {
+ pdf.saveGraphicsState();
+ }
- //------------------------------------
- TextSpanLayout layout = textRun.getLayout();
- logTextRun(runaci, layout);
- CharSequence chars = collectCharacters(runaci);
- runaci.first(); //Reset ACI
+ @Override
+ protected void restoreGraphicsState() {
+ pdf.restoreGraphicsState();
+ }
- final PDFGraphics2D pdf = (PDFGraphics2D)g2d;
+ @Override
+ protected void setInitialTransform(AffineTransform transform) {
+ createTextUtil();
+ textUtil.concatMatrix(transform);
+ }
- PDFTextUtil textUtil = new PDFTextUtil(pdf.fontInfo) {
+ private void createTextUtil() {
+ textUtil = new PDFTextUtil(pdf.fontInfo) {
protected void write(String code) {
pdf.currentStream.write(code);
}
@@ -97,142 +97,39 @@ class PDFTextPainter extends NativeTextP
pdf.currentStream.append(code);
}
};
+ }
- if (DEBUG) {
- log.debug("Text: " + chars);
- pdf.currentStream.write("%Text: " + chars + "\n");
- }
-
- GeneralPath debugShapes = null;
- if (DEBUG) {
- debugShapes = new GeneralPath();
- }
-
- Font[] fonts = findFonts(runaci);
- if (fonts == null || fonts.length == 0) {
- //Draw using Java2D when no native fonts are available
- textRun.getLayout().draw(g2d);
- return;
- }
-
- pdf.saveGraphicsState();
- textUtil.concatMatrix(g2d.getTransform());
- Shape imclip = g2d.getClip();
- pdf.writeClip(imclip);
-
- applyColorAndPaint(tpi, pdf);
+ @Override
+ protected void clip(Shape clip) {
+ pdf.writeClip(clip);
+ }
+ @Override
+ protected void beginTextObject() {
+ applyColorAndPaint(tpi);
textUtil.beginTextObject();
- textUtil.setFonts(fonts);
- boolean stroke = (tpi.strokePaint != null)
- && (tpi.strokeStroke != null);
+ boolean stroke = (tpi.strokePaint != null) && (tpi.strokeStroke != null);
textUtil.setTextRenderingMode(tpi.fillPaint != null, stroke, false);
+ }
- AffineTransform localTransform = new AffineTransform();
- Point2D prevPos = null;
- double prevVisibleCharWidth = 0.0;
- GVTGlyphVector gv = layout.getGlyphVector();
- for (int index = 0, c = gv.getNumGlyphs(); index < c; index++) {
- char ch = chars.charAt(index);
- boolean visibleChar = gv.isGlyphVisible(index)
- || (CharUtilities.isAnySpace(ch) && !CharUtilities.isZeroWidthSpace(ch));
- logCharacter(ch, layout, index, visibleChar);
- if (!visibleChar) {
- continue;
- }
- Point2D glyphPos = gv.getGlyphPosition(index);
-
- AffineTransform glyphTransform = gv.getGlyphTransform(index);
- //TODO Glyph transforms could be refined so not every char has to be painted
- //with its own TJ command (stretch/squeeze case could be optimized)
- if (log.isTraceEnabled()) {
- log.trace("pos " + glyphPos + ", transform " + glyphTransform);
- }
- if (DEBUG) {
- Shape sh = gv.getGlyphLogicalBounds(index);
- if (sh == null) {
- sh = new Ellipse2D.Double(glyphPos.getX(), glyphPos.getY(), 2, 2);
- }
- 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);
-
- boolean yPosChanged = (prevPos == null
- || prevPos.getY() != glyphPos.getY()
- || glyphTransform != null);
- if (yPosChanged) {
- if (index > 0) {
- textUtil.writeTJ();
- textUtil.writeTextMatrix(localTransform);
- }
- } else {
- double xdiff = glyphPos.getX() - prevPos.getX();
- //Width of previous character
- Font font = textUtil.getCurrentFont();
- double cw = prevVisibleCharWidth;
- double effxdiff = (1000 * xdiff) - cw;
- if (effxdiff != 0) {
- double adjust = (-effxdiff / font.getFontSize());
- textUtil.adjustGlyphTJ(adjust * 1000);
- }
- if (log.isTraceEnabled()) {
- log.trace("==> x diff: " + xdiff + ", " + effxdiff
- + ", charWidth: " + cw);
- }
- }
- Font f = textUtil.selectFontForChar(ch);
- char paintChar = (CharUtilities.isAnySpace(ch) ? ' ' : ch);
- char mappedChar = f.mapChar(paintChar);
- boolean encodingChanging = false; // used for single byte
- if (!textUtil.isMultiByteFont(f.getFontName())) {
- int encoding = mappedChar / 256;
- mappedChar = (char) (mappedChar % 256);
- if (textUtil.getCurrentEncoding() != encoding) {
- textUtil.setCurrentEncoding(encoding);
- encodingChanging = true;
- }
- }
- if (f != textUtil.getCurrentFont() || encodingChanging) {
- textUtil.writeTJ();
- textUtil.setCurrentFont(f);
- textUtil.writeTf(f);
- textUtil.writeTextMatrix(localTransform);
- }
- textUtil.writeTJMappedChar(mappedChar);
-
- //Update last position
- prevPos = glyphPos;
- prevVisibleCharWidth = textUtil.getCurrentFont().getCharWidth(chars.charAt(index));
- }
+ @Override
+ protected void endTextObject() {
textUtil.writeTJ();
textUtil.endTextObject();
- pdf.restoreGraphicsState();
- if (DEBUG) {
- g2d.setStroke(new BasicStroke(0));
- g2d.setColor(Color.LIGHT_GRAY);
- g2d.draw(debugShapes);
- }
}
- private void applyColorAndPaint(TextPaintInfo tpi, PDFGraphics2D pdf) {
+ private void applyColorAndPaint(TextPaintInfo tpi) {
Paint fillPaint = tpi.fillPaint;
Paint strokePaint = tpi.strokePaint;
Stroke stroke = tpi.strokeStroke;
int fillAlpha = PDFGraphics2D.OPAQUE;
if (fillPaint instanceof Color) {
- Color col = (Color)fillPaint;
+ Color col = (Color) fillPaint;
pdf.applyColor(col, true);
fillAlpha = col.getAlpha();
}
if (strokePaint instanceof Color) {
- Color col = (Color)strokePaint;
+ Color col = (Color) strokePaint;
pdf.applyColor(col, false);
}
pdf.applyPaint(fillPaint, true);
@@ -243,4 +140,46 @@ class PDFTextPainter extends NativeTextP
pdf.applyAlpha(fillAlpha, PDFGraphics2D.OPAQUE);
}
+ @Override
+ protected void positionGlyph(Point2D prevPos, Point2D glyphPos, boolean reposition) {
+ // TODO Glyph transforms could be refined so not every char has to be painted
+ // with its own TJ command (stretch/squeeze case could be optimized)
+ repositionNextGlyph = (prevPos == null
+ || prevPos.getY() != glyphPos.getY()
+ || reposition);
+ if (!repositionNextGlyph) {
+ double xdiff = glyphPos.getX() - prevPos.getX();
+ //Width of previous character
+ double cw = prevVisibleGlyphWidth;
+ double effxdiff = (1000 * xdiff) - cw;
+ if (effxdiff != 0) {
+ double adjust = (-effxdiff / font.getFontSize());
+ textUtil.adjustGlyphTJ(adjust * 1000);
+ }
+ }
+ }
+
+ @Override
+ protected void writeGlyph(char glyph, AffineTransform transform) {
+ prevVisibleGlyphWidth = font.getWidth(glyph);
+ boolean encodingChanging = false; // used for single byte
+ if (!textUtil.isMultiByteFont(font.getFontName())) {
+ int encoding = glyph / 256;
+ glyph = (char) (glyph % 256);
+ if (textUtil.getCurrentEncoding() != encoding) {
+ textUtil.setCurrentEncoding(encoding);
+ encodingChanging = true;
+ }
+ }
+ if (repositionNextGlyph || encodingChanging) {
+ textUtil.writeTJ();
+ if (font != textUtil.getCurrentFont() || encodingChanging) {
+ textUtil.setCurrentFont(font);
+ textUtil.writeTf(font);
+ }
+ textUtil.writeTextMatrix(transform);
+ }
+ textUtil.writeTJMappedChar(glyph);
+ }
+
}
Modified: xmlgraphics/fop/branches/Temp_FopFontsForSVG/src/java/org/apache/fop/svg/PDFTextUtil.java
URL: http://svn.apache.org/viewvc/xmlgraphics/fop/branches/Temp_FopFontsForSVG/src/java/org/apache/fop/svg/PDFTextUtil.java?rev=1508208&r1=1508207&r2=1508208&view=diff
==============================================================================
--- xmlgraphics/fop/branches/Temp_FopFontsForSVG/src/java/org/apache/fop/svg/PDFTextUtil.java (original)
+++ xmlgraphics/fop/branches/Temp_FopFontsForSVG/src/java/org/apache/fop/svg/PDFTextUtil.java Mon Jul 29 21:45:20 2013
@@ -30,7 +30,6 @@ import org.apache.fop.fonts.Typeface;
public abstract class PDFTextUtil extends org.apache.fop.pdf.PDFTextUtil {
private FontInfo fontInfo;
- private Font[] fonts;
private Font font;
private int encoding;
@@ -50,23 +49,6 @@ public abstract class PDFTextUtil extend
}
/**
- * Sets the current fonts for the text object. For every character, the suitable font will
- * be selected.
- * @param fonts the new fonts
- */
- public void setFonts(Font[] fonts) {
- this.fonts = fonts;
- }
-
- /**
- * Sets the current font for the text object.
- * @param font the new font
- */
- public void setFont(Font font) {
- setFonts(new Font[] {font});
- }
-
- /**
* Returns the current font in use.
* @return the current font or null if no font is currently active.
*/
@@ -123,27 +105,4 @@ public abstract class PDFTextUtil extend
}
}
- /**
- * Selects a font from the font list suitable to display the given character.
- * @param ch the character
- * @return the recommended Font to use
- */
- public Font selectFontForChar(char ch) {
- for (int i = 0, c = fonts.length; i < c; i++) {
- if (fonts[i].hasChar(ch)) {
- return fonts[i];
- }
- }
- return fonts[0]; //TODO Maybe fall back to painting with shapes
- }
-
- /**
- * Writes a char to the "TJ-Buffer".
- * @param ch the unmapped character
- */
- public void writeTJChar(char ch) {
- char mappedChar = font.mapChar(ch);
- writeTJMappedChar(mappedChar);
- }
-
}
Modified: xmlgraphics/fop/branches/Temp_FopFontsForSVG/src/java/org/apache/fop/svg/PDFTranscoder.java
URL: http://svn.apache.org/viewvc/xmlgraphics/fop/branches/Temp_FopFontsForSVG/src/java/org/apache/fop/svg/PDFTranscoder.java?rev=1508208&r1=1508207&r2=1508208&view=diff
==============================================================================
--- xmlgraphics/fop/branches/Temp_FopFontsForSVG/src/java/org/apache/fop/svg/PDFTranscoder.java (original)
+++ xmlgraphics/fop/branches/Temp_FopFontsForSVG/src/java/org/apache/fop/svg/PDFTranscoder.java Mon Jul 29 21:45:20 2013
@@ -31,7 +31,6 @@ import org.apache.avalon.framework.confi
import org.apache.batik.bridge.BridgeContext;
import org.apache.batik.bridge.UnitProcessor;
-import org.apache.batik.bridge.UserAgent;
import org.apache.batik.ext.awt.RenderingHintsKeyExt;
import org.apache.batik.transcoder.TranscoderException;
import org.apache.batik.transcoder.TranscoderOutput;
@@ -39,6 +38,7 @@ import org.apache.batik.transcoder.image
import org.apache.fop.Version;
import org.apache.fop.fonts.FontInfo;
+import org.apache.fop.svg.font.FOPFontFamilyResolverImpl;
/**
* <p>This class enables to transcode an input to a PDF document.</p>
@@ -88,7 +88,7 @@ public class PDFTranscoder extends Abstr
/**
* {@inheritDoc}
*/
- protected UserAgent createUserAgent() {
+ protected FOPTranscoderUserAgent createUserAgent() {
return new AbstractFOPTranscoder.FOPTranscoderUserAgent() {
// The PDF stuff wants everything at 72dpi
public float getPixelUnitToMillimeter() {
@@ -131,6 +131,8 @@ public class PDFTranscoder extends Abstr
} else {
graphics.setupDefaultFontInfo();
}
+ ((FOPTranscoderUserAgent) userAgent).setFontFamilyResolver(
+ new FOPFontFamilyResolverImpl(graphics.getFontInfo()));
} catch (Exception e) {
throw new TranscoderException(
"Error while setting up PDFDocumentGraphics2D", e);
Modified: xmlgraphics/fop/branches/Temp_FopFontsForSVG/src/java/org/apache/fop/svg/SVGUserAgent.java
URL: http://svn.apache.org/viewvc/xmlgraphics/fop/branches/Temp_FopFontsForSVG/src/java/org/apache/fop/svg/SVGUserAgent.java?rev=1508208&r1=1508207&r2=1508208&view=diff
==============================================================================
--- xmlgraphics/fop/branches/Temp_FopFontsForSVG/src/java/org/apache/fop/svg/SVGUserAgent.java (original)
+++ xmlgraphics/fop/branches/Temp_FopFontsForSVG/src/java/org/apache/fop/svg/SVGUserAgent.java Mon Jul 29 21:45:20 2013
@@ -21,6 +21,8 @@ package org.apache.fop.svg;
import java.awt.geom.AffineTransform;
+import org.apache.batik.gvt.font.FontFamilyResolver;
+
import org.apache.fop.apps.FOUserAgent;
/**
@@ -34,10 +36,11 @@ public class SVGUserAgent extends Simple
/**
* Creates a new SVGUserAgent.
* @param foUserAgent the FO user agent to associate with this SVG user agent
+ * @param fontFamilyResolver the font family resolver
* @param at the current transform
*/
- public SVGUserAgent(FOUserAgent foUserAgent, AffineTransform at) {
- super(foUserAgent.getSourcePixelUnitToMillimeter(), at);
+ public SVGUserAgent(FOUserAgent foUserAgent, FontFamilyResolver fontFamilyResolver, AffineTransform at) {
+ super(foUserAgent.getSourcePixelUnitToMillimeter(), at, fontFamilyResolver);
this.eventProducer = SVGEventProducer.Provider.get(foUserAgent.getEventBroadcaster());
}
@@ -45,8 +48,8 @@ public class SVGUserAgent extends Simple
* Creates a new SVGUserAgent.
* @param foUserAgent the FO user agent to associate with this SVG user agent
*/
- public SVGUserAgent(FOUserAgent foUserAgent) {
- this(foUserAgent, new AffineTransform());
+ public SVGUserAgent(FOUserAgent foUserAgent, FontFamilyResolver fontFamilyResolver) {
+ this(foUserAgent, fontFamilyResolver, new AffineTransform());
}
/**
Modified: xmlgraphics/fop/branches/Temp_FopFontsForSVG/src/java/org/apache/fop/svg/SimpleSVGUserAgent.java
URL: http://svn.apache.org/viewvc/xmlgraphics/fop/branches/Temp_FopFontsForSVG/src/java/org/apache/fop/svg/SimpleSVGUserAgent.java?rev=1508208&r1=1508207&r2=1508208&view=diff
==============================================================================
--- xmlgraphics/fop/branches/Temp_FopFontsForSVG/src/java/org/apache/fop/svg/SimpleSVGUserAgent.java (original)
+++ xmlgraphics/fop/branches/Temp_FopFontsForSVG/src/java/org/apache/fop/svg/SimpleSVGUserAgent.java Mon Jul 29 21:45:20 2013
@@ -26,6 +26,7 @@ import java.awt.geom.Dimension2D;
import javax.xml.parsers.SAXParserFactory;
import org.apache.batik.bridge.UserAgentAdapter;
+import org.apache.batik.gvt.font.FontFamilyResolver;
/**
* A simple SVG user agent.
@@ -35,14 +36,18 @@ import org.apache.batik.bridge.UserAgent
public class SimpleSVGUserAgent extends UserAgentAdapter {
private AffineTransform currentTransform = null;
+
private float pixelUnitToMillimeter = 0.0f;
+ private final FontFamilyResolver fontFamilyResolver;
+
/**
* Creates a new user agent.
* @param pixelUnitToMM the pixel to millimeter conversion factor currently in effect
* @param at the current transform
*/
- public SimpleSVGUserAgent(float pixelUnitToMM, AffineTransform at) {
+ public SimpleSVGUserAgent(float pixelUnitToMM, AffineTransform at, FontFamilyResolver fontFamilyResolver) {
+ this.fontFamilyResolver = fontFamilyResolver;
pixelUnitToMillimeter = pixelUnitToMM;
currentTransform = at;
}
@@ -122,5 +127,10 @@ public class SimpleSVGUserAgent extends
return new Dimension(100, 100);
}
+ @Override
+ public FontFamilyResolver getFontFamilyResolver() {
+ return fontFamilyResolver;
+ }
+
}
Added: xmlgraphics/fop/branches/Temp_FopFontsForSVG/src/java/org/apache/fop/svg/font/AggregatingFontFamilyResolver.java
URL: http://svn.apache.org/viewvc/xmlgraphics/fop/branches/Temp_FopFontsForSVG/src/java/org/apache/fop/svg/font/AggregatingFontFamilyResolver.java?rev=1508208&view=auto
==============================================================================
--- xmlgraphics/fop/branches/Temp_FopFontsForSVG/src/java/org/apache/fop/svg/font/AggregatingFontFamilyResolver.java (added)
+++ xmlgraphics/fop/branches/Temp_FopFontsForSVG/src/java/org/apache/fop/svg/font/AggregatingFontFamilyResolver.java Mon Jul 29 21:45:20 2013
@@ -0,0 +1,70 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+/* $Id$ */
+
+package org.apache.fop.svg.font;
+
+import java.util.Arrays;
+import java.util.List;
+
+import org.apache.batik.gvt.font.FontFamilyResolver;
+import org.apache.batik.gvt.font.GVTFontFamily;
+
+public class AggregatingFontFamilyResolver implements FontFamilyResolver {
+
+ private final List<FontFamilyResolver> resolvers;
+
+ public AggregatingFontFamilyResolver(FontFamilyResolver... resolvers) {
+ this.resolvers = Arrays.<FontFamilyResolver>asList(resolvers);
+ }
+
+ public String lookup(String familyName) {
+ for (FontFamilyResolver resolver : resolvers) {
+ String lookup = resolver.lookup(familyName);
+ if (lookup != null) {
+ return lookup;
+ }
+ }
+ return null;
+ }
+
+ public GVTFontFamily resolve(String familyName) {
+ for (FontFamilyResolver resolver : resolvers) {
+ GVTFontFamily family = resolver.resolve(familyName);
+ if (family != null) {
+ return family;
+ }
+ }
+ return null;
+ }
+
+ public GVTFontFamily getDefault() {
+ return resolve("any");
+ }
+
+ public GVTFontFamily getFamilyThatCanDisplay(char c) {
+ for (FontFamilyResolver resolver : resolvers) {
+ GVTFontFamily family = resolver.getFamilyThatCanDisplay(c);
+ if (family != null) {
+ return family;
+ }
+ }
+ return null;
+ }
+
+}
Propchange: xmlgraphics/fop/branches/Temp_FopFontsForSVG/src/java/org/apache/fop/svg/font/AggregatingFontFamilyResolver.java
------------------------------------------------------------------------------
svn:eol-style = native
Propchange: xmlgraphics/fop/branches/Temp_FopFontsForSVG/src/java/org/apache/fop/svg/font/AggregatingFontFamilyResolver.java
------------------------------------------------------------------------------
svn:keywords = Revision Id
---------------------------------------------------------------------
To unsubscribe, e-mail: fop-commits-unsubscribe@xmlgraphics.apache.org
For additional commands, e-mail: fop-commits-help@xmlgraphics.apache.org