Added: xmlgraphics/fop/trunk/src/java/org/apache/fop/svg/NativeTextPainter.java
URL:
http://svn.apache.org/viewvc/xmlgraphics/fop/trunk/src/java/org/apache/fop/svg/NativeTextPainter.java?rev=766594&view=auto
==============================================================================
--- xmlgraphics/fop/trunk/src/java/org/apache/fop/svg/NativeTextPainter.java
(added)
+++ xmlgraphics/fop/trunk/src/java/org/apache/fop/svg/NativeTextPainter.java
Mon Apr 20 06:50:59 2009
@@ -0,0 +1,224 @@
+/*
+ * 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;
+
+import java.awt.Graphics2D;
+import java.awt.font.TextAttribute;
+import java.io.IOException;
+import java.text.AttributedCharacterIterator;
+import java.util.Iterator;
+import java.util.List;
+
+import org.apache.batik.bridge.SVGFontFamily;
+import org.apache.batik.gvt.font.GVTFont;
+import org.apache.batik.gvt.font.GVTFontFamily;
+import org.apache.batik.gvt.renderer.StrokingTextPainter;
+import org.apache.batik.gvt.text.GVTAttributedCharacterIterator;
+import org.apache.batik.gvt.text.TextSpanLayout;
+import org.apache.commons.logging.Log;
+import org.apache.commons.logging.LogFactory;
+
+import org.apache.fop.fonts.Font;
+import org.apache.fop.fonts.FontInfo;
+import org.apache.fop.fonts.FontTriplet;
+import org.apache.fop.util.CharUtilities;
+
+/**
+ * Abstract base class for text painters that use specialized text commands
native to an output
+ * format to render text.
+ */
+public abstract class NativeTextPainter extends StrokingTextPainter {
+
+ /** the logger for this class */
+ protected Log log = LogFactory.getLog(NativeTextPainter.class);
+
+ /** the font collection */
+ protected final FontInfo fontInfo;
+
+ /**
+ * Creates a new instance.
+ * @param fontInfo the font collection
+ */
+ public NativeTextPainter(FontInfo fontInfo) {
+ this.fontInfo = fontInfo;
+ }
+
+ /**
+ * Indicates whether the given {...@link Graphics2D} instance if
compatible with this text painter
+ * implementation.
+ * @param g2d the instance to check
+ * @return true if the instance is compatible.
+ */
+ protected abstract boolean isSupported(Graphics2D g2d);
+
+ /**
+ * Paints a single text run.
+ * @param textRun the text run
+ * @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;
+
+ /** {...@inheritdoc} */
+ protected void paintTextRuns(List textRuns, Graphics2D g2d) {
+ if (log.isTraceEnabled()) {
+ log.trace("paintTextRuns: count = " + textRuns.size());
+ }
+ if (!isSupported(g2d)) {
+ super.paintTextRuns(textRuns, g2d);
+ return;
+ }
+ for (int i = 0; i < textRuns.size(); i++) {
+ TextRun textRun = (TextRun)textRuns.get(i);
+ try {
+ paintTextRun(textRun, g2d);
+ } catch (IOException ioe) {
+ //No other possibility than to use a RuntimeException
+ throw new RuntimeException(ioe);
+ }
+ }
+ }
+
+ /**
+ * 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) {
+ List fonts = new java.util.ArrayList();
+ List gvtFonts = (List) 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 = ((posture != null) && (posture.floatValue() > 0.0))
+ ? Font.STYLE_ITALIC : Font.STYLE_NORMAL;
+ int weight = ((taWeight != null)
+ && (taWeight.floatValue() > 1.0)) ? Font.WEIGHT_BOLD
+ : Font.WEIGHT_NORMAL;
+
+ 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);
+ if (gvtFont != null) {
+ try {
+ String gvtFontFamily = gvtFont.getFamilyName(); //Not
available in Batik 1.6!
+ if (log.isDebugEnabled()) {
+ log.debug("Matching font family: " + gvtFontFamily);
+ }
+ if (fontInfo.hasFont(gvtFontFamily, style, weight)) {
+ FontTriplet triplet = fontInfo.fontLookup(gvtFontFamily,
style,
+ weight);
+ int fsize = (int)(fontSize.floatValue() * 1000);
+ fonts.add(fontInfo.getFontInstance(triplet, fsize));
+ }
+ firstFontFamily = gvtFontFamily;
+ } catch (Exception e) {
+ //Most likely NoSuchMethodError here when using Batik 1.6
+ //Just skip this section in this case
+ }
+ }
+
+ if (gvtFonts != null) {
+ Iterator i = gvtFonts.iterator();
+ while (i.hasNext()) {
+ GVTFontFamily fam = (GVTFontFamily) i.next();
+ if (fam instanceof SVGFontFamily) {
+ return null; //Let Batik paint this text!
+ }
+ String fontFamily = fam.getFamilyName();
+ if (log.isDebugEnabled()) {
+ log.debug("Matching font family: " + fontFamily);
+ }
+ if (fontInfo.hasFont(fontFamily, style, weight)) {
+ FontTriplet triplet = fontInfo.fontLookup(fontFamily,
style,
+ weight);
+ int fsize = (int)(fontSize.floatValue() * 1000);
+ fonts.add(fontInfo.getFontInstance(triplet, fsize));
+ }
+ if (firstFontFamily == null) {
+ firstFontFamily = fontFamily;
+ }
+ }
+ }
+ if (fonts.size() == 0) {
+ 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);
+ int fsize = (int)(fontSize.floatValue() * 1000);
+ fonts.add(fontInfo.getFontInstance(triplet, fsize));
+ }
+ return (Font[])fonts.toArray(new Font[fonts.size()]);
+ }
+
+ /**
+ * Collects all characters from an {...@link AttributedCharacterIterator}.
+ * @param runaci the character iterator
+ * @return the characters
+ */
+ protected CharSequence collectCharacters(AttributedCharacterIterator
runaci) {
+ StringBuffer chars = new StringBuffer();
+ for (runaci.first(); runaci.getIndex() < runaci.getEndIndex();) {
+ chars.append(runaci.current());
+ runaci.next();
+ }
+ return chars;
+ }
+
+ protected final void logTextRun(AttributedCharacterIterator runaci,
TextSpanLayout layout) {
+ if (log.isTraceEnabled()) {
+ int charCount = runaci.getEndIndex() - runaci.getBeginIndex();
+ log.trace("================================================");
+ log.trace("New text run:");
+ log.trace("char count: " + charCount);
+ log.trace("range: "
+ + runaci.getBeginIndex() + " - " + runaci.getEndIndex());
+ log.trace("glyph count: " + layout.getGlyphCount());
//=getNumGlyphs()
+ }
+ }
+
+ protected final void logCharacter(char ch, TextSpanLayout layout, int
index,
+ boolean visibleChar) {
+ if (log.isTraceEnabled()) {
+ log.trace("glyph " + index
+ + " -> " + layout.getGlyphIndex(index) + " => " + ch);
+ if (CharUtilities.isAnySpace(ch) && ch != 32) {
+ log.trace("Space found: " + Integer.toHexString(ch));
+ } else if (ch == CharUtilities.ZERO_WIDTH_JOINER) {
+ log.trace("ZWJ found: " + Integer.toHexString(ch));
+ } else if (ch == CharUtilities.SOFT_HYPHEN) {
+ log.trace("Soft hyphen found: " + Integer.toHexString(ch));
+ }
+ if (!visibleChar) {
+ log.trace("Invisible glyph found: " + Integer.toHexString(ch));
+ }
+ }
+ }
+
+
+}
Propchange:
xmlgraphics/fop/trunk/src/java/org/apache/fop/svg/NativeTextPainter.java
------------------------------------------------------------------------------
svn:eol-style = native
Propchange:
xmlgraphics/fop/trunk/src/java/org/apache/fop/svg/NativeTextPainter.java
------------------------------------------------------------------------------
svn:keywords = Id
Modified:
xmlgraphics/fop/trunk/src/java/org/apache/fop/svg/PDFBridgeContext.java
URL:
http://svn.apache.org/viewvc/xmlgraphics/fop/trunk/src/java/org/apache/fop/svg/PDFBridgeContext.java?rev=766594&r1=766593&r2=766594&view=diff
==============================================================================
--- xmlgraphics/fop/trunk/src/java/org/apache/fop/svg/PDFBridgeContext.java
(original)
+++ xmlgraphics/fop/trunk/src/java/org/apache/fop/svg/PDFBridgeContext.java Mon
Apr 20 06:50:59 2009
@@ -26,10 +26,12 @@
import org.apache.batik.bridge.SVGTextElementBridge;
import org.apache.batik.bridge.UserAgent;
import org.apache.batik.gvt.TextPainter;
-import org.apache.fop.fonts.FontInfo;
+
import org.apache.xmlgraphics.image.loader.ImageManager;
import org.apache.xmlgraphics.image.loader.ImageSessionContext;
+import org.apache.fop.fonts.FontInfo;
+
/**
* BridgeContext which registers the custom bridges for PDF output.
*/
@@ -38,11 +40,9 @@
/**
* Constructs a new bridge context.
* @param userAgent the user agent
- * @param loader the Document Loader to use for referenced documents.
+ * @param documentLoader the Document Loader to use for referenced
documents.
* @param fontInfo the font list for the text painter, may be null
* in which case text is painted as shapes
- * @param linkTransform AffineTransform to properly place links,
- * may be null
* @param imageManager an image manager
* @param imageSessionContext an image session context
* @param linkTransform AffineTransform to properly place links,
@@ -52,7 +52,8 @@
FontInfo fontInfo, ImageManager imageManager,
ImageSessionContext imageSessionContext,
AffineTransform linkTransform) {
- super(userAgent, documentLoader, fontInfo, imageManager,
imageSessionContext, linkTransform);
+ super(userAgent, documentLoader, fontInfo,
+ imageManager, imageSessionContext, linkTransform);
}
/**
Modified:
xmlgraphics/fop/trunk/src/java/org/apache/fop/svg/PDFDocumentGraphics2DConfigurator.java
URL:
http://svn.apache.org/viewvc/xmlgraphics/fop/trunk/src/java/org/apache/fop/svg/PDFDocumentGraphics2DConfigurator.java?rev=766594&r1=766593&r2=766594&view=diff
==============================================================================
---
xmlgraphics/fop/trunk/src/java/org/apache/fop/svg/PDFDocumentGraphics2DConfigurator.java
(original)
+++
xmlgraphics/fop/trunk/src/java/org/apache/fop/svg/PDFDocumentGraphics2DConfigurator.java
Mon Apr 20 06:50:59 2009
@@ -55,6 +55,22 @@
//Fonts
try {
+ FontInfo fontInfo = createFontInfo(cfg);
+ graphics.setFontInfo(fontInfo);
+ } catch (FOPException e) {
+ throw new ConfigurationException("Error while setting up fonts",
e);
+ }
+ }
+
+ /**
+ * Creates the {...@link FontInfo} instance for the given configuration.
+ * @param cfg the configuration
+ * @return the font collection
+ * @throws FOPException if an error occurs while setting up the fonts
+ */
+ public static FontInfo createFontInfo(Configuration cfg) throws
FOPException {
+ FontInfo fontInfo = new FontInfo();
+ if (cfg != null) {
FontResolver fontResolver =
FontManager.createMinimalFontResolver();
//TODO The following could be optimized by retaining the
FontManager somewhere
FontManager fontManager = new FontManager();
@@ -73,12 +89,11 @@
if (fontManager.useCache()) {
fontManager.getFontCache().save();
}
- FontInfo fontInfo = new FontInfo();
FontSetup.setup(fontInfo, fontInfoList, fontResolver);
- graphics.setFontInfo(fontInfo);
- } catch (FOPException e) {
- throw new ConfigurationException("Error while setting up fonts",
e);
+ } else {
+ FontSetup.setup(fontInfo);
}
+ return fontInfo;
}
}
Modified: xmlgraphics/fop/trunk/src/java/org/apache/fop/svg/PDFTextPainter.java
URL:
http://svn.apache.org/viewvc/xmlgraphics/fop/trunk/src/java/org/apache/fop/svg/PDFTextPainter.java?rev=766594&r1=766593&r2=766594&view=diff
==============================================================================
--- xmlgraphics/fop/trunk/src/java/org/apache/fop/svg/PDFTextPainter.java
(original)
+++ xmlgraphics/fop/trunk/src/java/org/apache/fop/svg/PDFTextPainter.java Mon
Apr 20 06:50:59 2009
@@ -25,28 +25,18 @@
import java.awt.Paint;
import java.awt.Shape;
import java.awt.Stroke;
-import java.awt.font.TextAttribute;
import java.awt.geom.AffineTransform;
import java.awt.geom.Ellipse2D;
import java.awt.geom.GeneralPath;
import java.awt.geom.Point2D;
-import java.lang.reflect.Method;
import java.text.AttributedCharacterIterator;
-import java.util.Iterator;
-import java.util.List;
-import org.apache.batik.bridge.SVGFontFamily;
-import org.apache.batik.gvt.font.GVTFont;
-import org.apache.batik.gvt.font.GVTFontFamily;
import org.apache.batik.gvt.font.GVTGlyphVector;
-import org.apache.batik.gvt.renderer.StrokingTextPainter;
-import org.apache.batik.gvt.text.GVTAttributedCharacterIterator;
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.fonts.FontTriplet;
import org.apache.fop.util.CharUtilities;
/**
@@ -59,193 +49,159 @@
*
* @version $Id$
*/
-public class PDFTextPainter extends StrokingTextPainter {
+class PDFTextPainter extends NativeTextPainter {
private static final boolean DEBUG = false;
- private final boolean strokeText = false;
- private final FontInfo fontInfo;
-
/**
* Create a new PDF text painter with the given font information.
* @param fi the font info
*/
public PDFTextPainter(FontInfo fi) {
- fontInfo = fi;
+ super(fi);
}
/** {...@inheritdoc} */
- protected void paintTextRuns(List textRuns, Graphics2D g2d) {
- if (DEBUG) {
- System.out.println("paintTextRuns: count = " + textRuns.size());
- //fontInfo.dumpAllTripletsToSystemOut();
- }
- if (!(g2d instanceof PDFGraphics2D) || strokeText) {
- super.paintTextRuns(textRuns, g2d);
+ protected boolean isSupported(Graphics2D g2d) {
+ return g2d instanceof PDFGraphics2D;
+ }
+
+ /** {...@inheritdoc} */
+ protected void paintTextRun(TextRun textRun, Graphics2D g2d) {
+ 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 PDFGraphics2D pdf = (PDFGraphics2D)g2d;
PDFTextUtil textUtil = new PDFTextUtil(pdf.fontInfo) {
protected void write(String code) {
pdf.currentStream.write(code);
}
};
- for (int i = 0; i < textRuns.size(); i++) {
- TextRun textRun = (TextRun)textRuns.get(i);
- AttributedCharacterIterator runaci = textRun.getACI();
- runaci.first();
- TextPaintInfo tpi = (TextPaintInfo)runaci.getAttribute(PAINT_INFO);
- if (tpi == null || !tpi.visible) {
- continue;
- }
- if ((tpi != null) && (tpi.composite != null)) {
- g2d.setComposite(tpi.composite);
- }
+ if (DEBUG) {
+ log.debug("Text: " + chars);
+ pdf.currentStream.write("%Text: " + chars + "\n");
+ }
- //------------------------------------
- TextSpanLayout layout = textRun.getLayout();
- if (DEBUG) {
- int charCount = runaci.getEndIndex() - runaci.getBeginIndex();
-
System.out.println("================================================");
- System.out.println("New text run:");
- System.out.println("char count: " + charCount);
- System.out.println("range: "
- + runaci.getBeginIndex() + " - " +
runaci.getEndIndex());
- System.out.println("glyph count: " + layout.getGlyphCount());
//=getNumGlyphs()
- }
- //Gather all characters of the run
- StringBuffer chars = new StringBuffer();
- for (runaci.first(); runaci.getIndex() < runaci.getEndIndex();) {
- chars.append(runaci.current());
- runaci.next();
- }
- runaci.first();
- if (DEBUG) {
- System.out.println("Text: " + chars);
- pdf.currentStream.write("%Text: " + chars + "\n");
- }
+ GeneralPath debugShapes = null;
+ if (DEBUG) {
+ debugShapes = new GeneralPath();
+ }
- 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;
+ }
- Font[] fonts = findFonts(runaci);
- if (fonts == null || fonts.length == 0) {
- //Draw using Java2D
- textRun.getLayout().draw(g2d);
+ textUtil.saveGraphicsState();
+ textUtil.concatMatrix(g2d.getTransform());
+ Shape imclip = g2d.getClip();
+ pdf.writeClip(imclip);
+
+ applyColorAndPaint(tpi, pdf);
+
+ textUtil.beginTextObject();
+ textUtil.setFonts(fonts);
+ 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);
- textUtil.saveGraphicsState();
- textUtil.concatMatrix(g2d.getTransform());
- Shape imclip = g2d.getClip();
- pdf.writeClip(imclip);
-
- applyColorAndPaint(tpi, pdf);
-
- textUtil.beginTextObject();
- textUtil.setFonts(fonts);
- 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));
- if (DEBUG) {
- System.out.println("glyph " + index
- + " -> " + layout.getGlyphIndex(index) + " => " +
ch);
- if (CharUtilities.isAnySpace(ch) && ch != 32) {
- System.out.println("Space found: " +
Integer.toHexString(ch));
- }
- if (ch == CharUtilities.ZERO_WIDTH_JOINER) {
- System.out.println("ZWJ found: " +
Integer.toHexString(ch));
- }
- if (ch == CharUtilities.SOFT_HYPHEN) {
- System.out.println("Soft hyphen found: " +
Integer.toHexString(ch));
- }
- if (!visibleChar) {
- System.out.println("Invisible glyph found: " +
Integer.toHexString(ch));
- }
- }
- if (!visibleChar) {
- continue;
- }
- Point2D p = 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 (DEBUG) {
- System.out.println("pos " + p + ", transform " +
glyphTransform);
- Shape sh;
- sh = gv.getGlyphLogicalBounds(index);
- if (sh == null) {
- sh = new Ellipse2D.Double(p.getX(), p.getY(), 2, 2);
- }
- debugShapes.append(sh, false);
- }
-
- //Exact position of the glyph
- localTransform.setToIdentity();
- localTransform.translate(p.getX(), p.getY());
- if (glyphTransform != null) {
- localTransform.concatenate(glyphTransform);
- }
- localTransform.scale(1, -1);
-
- boolean yPosChanged = (prevPos == null
- || prevPos.getY() != p.getY()
- || glyphTransform != null);
- if (yPosChanged) {
- if (index > 0) {
- textUtil.writeTJ();
- textUtil.writeTextMatrix(localTransform);
- }
- } else {
- double xdiff = p.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 (DEBUG) {
- System.out.println("==> x diff: " + xdiff + ", " +
effxdiff
- + ", charWidth: " + cw);
- }
- }
- Font f = textUtil.selectFontForChar(ch);
- if (f != textUtil.getCurrentFont()) {
+ 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.setCurrentFont(f);
- textUtil.writeTf(f);
textUtil.writeTextMatrix(localTransform);
}
- char paintChar = (CharUtilities.isAnySpace(ch) ? ' ' : ch);
- textUtil.writeTJChar(paintChar);
-
- //Update last position
- prevPos = p;
- prevVisibleCharWidth =
textUtil.getCurrentFont().getCharWidth(chars.charAt(index));
- }
- textUtil.writeTJ();
- textUtil.endTextObject();
- textUtil.restoreGraphicsState();
- if (DEBUG) {
- g2d.setStroke(new BasicStroke(0));
- g2d.setColor(Color.LIGHT_GRAY);
- g2d.draw(debugShapes);
- }
+ } 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);
+ if (f != textUtil.getCurrentFont()) {
+ textUtil.writeTJ();
+ textUtil.setCurrentFont(f);
+ textUtil.writeTf(f);
+ textUtil.writeTextMatrix(localTransform);
+ }
+ char paintChar = (CharUtilities.isAnySpace(ch) ? ' ' : ch);
+ textUtil.writeTJChar(paintChar);
+
+ //Update last position
+ prevPos = glyphPos;
+ prevVisibleCharWidth =
textUtil.getCurrentFont().getCharWidth(chars.charAt(index));
+ }
+ textUtil.writeTJ();
+ textUtil.endTextObject();
+ textUtil.restoreGraphicsState();
+ if (DEBUG) {
+ g2d.setStroke(new BasicStroke(0));
+ g2d.setColor(Color.LIGHT_GRAY);
+ g2d.draw(debugShapes);
}
}
@@ -271,85 +227,4 @@
pdf.applyAlpha(fillAlpha, PDFGraphics2D.OPAQUE);
}
- private Font[] findFonts(AttributedCharacterIterator aci) {
- List fonts = new java.util.ArrayList();
- List gvtFonts = (List) 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 = ((posture != null) && (posture.floatValue() > 0.0))
- ? Font.STYLE_ITALIC : Font.STYLE_NORMAL;
- int weight = ((taWeight != null)
- && (taWeight.floatValue() > 1.0)) ? Font.WEIGHT_BOLD
- : Font.WEIGHT_NORMAL;
-
- 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);
- if (gvtFont != null) {
- try {
- Method method = gvtFont.getClass().getMethod("getFamilyName",
null);
- String gvtFontFamily = (String)method.invoke(gvtFont, null);
- //TODO Uncomment the following line when Batik 1.7 is shipped
with FOP
- //String gvtFontFamily = gvtFont.getFamilyName(); //Not
available in Batik 1.6
- if (DEBUG) {
- System.out.print(gvtFontFamily + ", ");
- }
- if (fontInfo.hasFont(gvtFontFamily, style, weight)) {
- FontTriplet triplet = fontInfo.fontLookup(gvtFontFamily,
style,
- weight);
- int fsize = (int)(fontSize.floatValue() * 1000);
- fonts.add(fontInfo.getFontInstance(triplet, fsize));
- }
- firstFontFamily = gvtFontFamily;
- } catch (Exception e) {
- //Most likely NoSuchMethodError here when using Batik 1.6
- //Just skip this section in this case
- }
- }
-
- if (gvtFonts != null) {
- Iterator i = gvtFonts.iterator();
- while (i.hasNext()) {
- GVTFontFamily fam = (GVTFontFamily) i.next();
- if (fam instanceof SVGFontFamily) {
- return null; //Let Batik paint this text!
- }
- String fontFamily = fam.getFamilyName();
- if (DEBUG) {
- System.out.print(fontFamily + ", ");
- }
- if (fontInfo.hasFont(fontFamily, style, weight)) {
- FontTriplet triplet = fontInfo.fontLookup(fontFamily,
style,
- weight);
- int fsize = (int)(fontSize.floatValue() * 1000);
- fonts.add(fontInfo.getFontInstance(triplet, fsize));
- }
- if (firstFontFamily == null) {
- firstFontFamily = fontFamily;
- }
- }
- }
- if (fonts.size() == 0) {
- 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);
- int fsize = (int)(fontSize.floatValue() * 1000);
- fonts.add(fontInfo.getFontInstance(triplet, fsize));
- }
- if (DEBUG) {
- System.out.println();
- }
- return (Font[])fonts.toArray(new Font[fonts.size()]);
- }
-
}
\ No newline at end of file
Modified: xmlgraphics/fop/trunk/src/java/org/apache/fop/svg/PDFTranscoder.java
URL:
http://svn.apache.org/viewvc/xmlgraphics/fop/trunk/src/java/org/apache/fop/svg/PDFTranscoder.java?rev=766594&r1=766593&r2=766594&view=diff
==============================================================================
--- xmlgraphics/fop/trunk/src/java/org/apache/fop/svg/PDFTranscoder.java
(original)
+++ xmlgraphics/fop/trunk/src/java/org/apache/fop/svg/PDFTranscoder.java Mon
Apr 20 06:50:59 2009
@@ -23,34 +23,19 @@
import java.io.BufferedOutputStream;
import java.io.IOException;
import java.io.OutputStream;
-import java.io.InputStream;
-
-import javax.xml.transform.Source;
-import javax.xml.transform.stream.StreamSource;
import org.w3c.dom.Document;
import org.w3c.dom.svg.SVGLength;
import org.apache.avalon.framework.configuration.Configurable;
import org.apache.avalon.framework.configuration.Configuration;
-import org.apache.avalon.framework.configuration.ConfigurationException;
-import org.apache.avalon.framework.configuration.DefaultConfiguration;
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;
-import org.apache.batik.transcoder.TranscodingHints;
import org.apache.batik.transcoder.image.ImageTranscoder;
-import org.apache.batik.transcoder.keys.BooleanKey;
-import org.apache.batik.transcoder.keys.FloatKey;
-import org.apache.batik.util.ParsedURL;
-
-import org.apache.xmlgraphics.image.loader.ImageContext;
-import org.apache.xmlgraphics.image.loader.ImageManager;
-import org.apache.xmlgraphics.image.loader.ImageSessionContext;
-import org.apache.xmlgraphics.image.loader.impl.AbstractImageSessionContext;
import org.apache.fop.Version;
import org.apache.fop.fonts.FontInfo;
@@ -91,27 +76,9 @@
public class PDFTranscoder extends AbstractFOPTranscoder
implements Configurable {
- /**
- * The key is used to specify the resolution for on-the-fly images
generated
- * due to complex effects like gradients and filters.
- */
- public static final TranscodingHints.Key KEY_DEVICE_RESOLUTION = new
FloatKey();
-
- /**
- * The key is used to specify whether the available fonts should be
automatically
- * detected. The alternative is to configure the transcoder manually using
a configuration
- * file.
- */
- public static final TranscodingHints.Key KEY_AUTO_FONTS = new BooleanKey();
-
- private Configuration cfg = null;
-
/** Graphics2D instance that is used to paint to */
protected PDFDocumentGraphics2D graphics = null;
- private ImageManager imageManager;
- private ImageSessionContext imageSessionContext;
-
/**
* Constructs a new <tt>PDFTranscoder</tt>.
*/
@@ -133,11 +100,6 @@
};
}
- /** {...@inheritdoc} */
- public void configure(Configuration cfg) throws ConfigurationException {
- this.cfg = cfg;
- }
-
/**
* Transcodes the specified Document as an image in the specified output.
*
@@ -155,28 +117,13 @@
+ Version.getVersion()
+ ": PDF Transcoder for Batik");
if (hints.containsKey(KEY_DEVICE_RESOLUTION)) {
-
graphics.setDeviceDPI(((Float)hints.get(KEY_DEVICE_RESOLUTION)).floatValue());
+ graphics.setDeviceDPI(getDeviceResolution());
}
setupImageInfrastructure(uri);
try {
- Configuration effCfg = this.cfg;
- if (effCfg == null) {
- //By default, enable font auto-detection if no cfg is given
- boolean autoFonts = true;
- if (hints.containsKey(KEY_AUTO_FONTS)) {
- autoFonts =
((Boolean)hints.get(KEY_AUTO_FONTS)).booleanValue();
- }
- if (autoFonts) {
- DefaultConfiguration c = new
DefaultConfiguration("pdf-transcoder");
- DefaultConfiguration fonts = new
DefaultConfiguration("fonts");
- c.addChild(fonts);
- DefaultConfiguration autodetect = new
DefaultConfiguration("auto-detect");
- fonts.addChild(autodetect);
- effCfg = c;
- }
- }
+ Configuration effCfg = getEffectiveConfiguration();
if (effCfg != null) {
PDFDocumentGraphics2DConfigurator configurator
@@ -242,39 +189,6 @@
}
}
- private void setupImageInfrastructure(final String baseURI) {
- final ImageContext imageContext = new ImageContext() {
- public float getSourceResolution() {
- return 25.4f / userAgent.getPixelUnitToMillimeter();
- }
- };
- this.imageManager = new ImageManager(imageContext);
- this.imageSessionContext = new AbstractImageSessionContext() {
-
- public ImageContext getParentContext() {
- return imageContext;
- }
-
- public float getTargetResolution() {
- return graphics.getDeviceDPI();
- }
-
- public Source resolveURI(String uri) {
- System.out.println("resolve " + uri);
- try {
- ParsedURL url = new ParsedURL(baseURI, uri);
- InputStream in = url.openStream();
- StreamSource source = new StreamSource(in, url.toString());
- return source;
- } catch (IOException ioe) {
- userAgent.displayError(ioe);
- return null;
- }
- }
-
- };
- }
-
/** {...@inheritdoc} */
protected BridgeContext createBridgeContext() {
//For compatibility with Batik 1.6
@@ -288,7 +202,7 @@
fontInfo = null;
}
BridgeContext ctx = new PDFBridgeContext(userAgent, fontInfo,
- this.imageManager, this.imageSessionContext);
+ getImageManager(), getImageSessionContext());
return ctx;
}
Modified: xmlgraphics/fop/trunk/status.xml
URL:
http://svn.apache.org/viewvc/xmlgraphics/fop/trunk/status.xml?rev=766594&r1=766593&r2=766594&view=diff
==============================================================================
--- xmlgraphics/fop/trunk/status.xml (original)
+++ xmlgraphics/fop/trunk/status.xml Mon Apr 20 06:50:59 2009
@@ -58,6 +58,10 @@
documents. Example: the fix of marks layering will be such a case when
it's done.
-->
<release version="FOP Trunk" date="TBD">
+ <action context="Renderers" dev="JM" type="add">
+ Added a custom text painter for rendering SVG text using text
operators when rendering
+ to PostScript or EPS. Text is no longer painted as shapes, thus
creating much smaller files.
+ </action>
<action context="Renderers" dev="JM" type="fix">
Fixed a bug that left the PrintRenderer unconfigured even if a
configuration was
specified for "application/X-fop-print".
---------------------------------------------------------------------
To unsubscribe, e-mail: [email protected]
For additional commands, e-mail: [email protected]