import org.apache.fop.apps.FOPException;
public class FontInfo {
- Hashtable usedFonts;
- Hashtable triplets; // look up a font-triplet to find a font-name
- Hashtable fonts; // look up a font-name to get a font (that implements FontMetric at least)
-
- public FontInfo() {
- this.triplets = new Hashtable();
- this.fonts = new Hashtable();
- this.usedFonts = new Hashtable();
- }
-
- public void addFontProperties(String name, String family, String style, String weight) {
- /* add the given family, style and weight as a lookup for the font
- with the given name */
-
- String key = createFontKey(family,style,weight);
- this.triplets.put(key,name);
- }
-
- public void addMetrics(String name, FontMetric metrics) {
- // add the given metrics as a font with the given name
-
- this.fonts.put(name,metrics);
- }
-
- public String fontLookup(String family, String style, String weight)
- throws FOPException
- {
- return fontLookup(createFontKey(family,style,weight));
+ Hashtable usedFonts;
+ Hashtable triplets; // look up a font-triplet to find a font-name
+ Hashtable fonts; // look up a font-name to get a font (that implements FontMetric at least)
+
+ public FontInfo() {
+ this.triplets = new Hashtable();
+ this.fonts = new Hashtable();
+ this.usedFonts = new Hashtable();
}
-
- public String fontLookup(String key)
- throws FOPException
- {
-
- String f = (String)this.triplets.get(key);
- if (f == null) {
- int i = key.indexOf(',');
- String s = "any"+key.substring(i);
- f = (String)this.triplets.get(s);
- if (f == null) {
- f = (String)this.triplets.get("any,normal,normal");
- if (f == null) {
- throw new FOPException("no default font defined by OutputConverter");
- }
- MessageHandler.errorln("WARNING: defaulted font to any,normal,normal");
- }
- MessageHandler.errorln("WARNING: unknown font "+key+" so defaulted font to any");
- }
-
- usedFonts.put(f, fonts.get(f));
- return f;
+
+ public void addFontProperties(String name, String family,
+ String style, String weight) {
+ /* add the given family, style and weight as a lookup for the font
+ with the given name */
+
+ String key = createFontKey(family, style, weight);
+ this.triplets.put(key, name);
+ }
+
+ public void addMetrics(String name, FontMetric metrics) {
+ // add the given metrics as a font with the given name
+
+ this.fonts.put(name, metrics);
+ }
+
+ public String fontLookup(String family, String style,
+ String weight) throws FOPException {
+ return fontLookup(createFontKey(family, style, weight));
+ }
+
+ public String fontLookup(String key) throws FOPException {
+
+ String f = (String) this.triplets.get(key);
+ if (f == null) {
+ int i = key.indexOf(',');
+ String s = "any"+key.substring(i);
+ f = (String) this.triplets.get(s);
+ if (f == null) {
+ f = (String) this.triplets.get("any,normal,normal");
+ if (f == null) {
+ throw new FOPException("no default font defined by OutputConverter");
+ }
+ MessageHandler.errorln("WARNING: defaulted font to any,normal,normal");
+ }
+ MessageHandler.errorln("WARNING: unknown font "+key + " so defaulted font to any");
+ }
+
+ usedFonts.put(f, fonts.get(f));
+ return f;
+ }
+
+ public boolean hasFont(String family, String style, String weight) {
+ String key = createFontKey(family, style, weight);
+ return this.triplets.get(key) != null;
}
/**
* Creates a key from the given strings
*/
- public static String createFontKey(String family, String style, String weight)
- {
- int i;
-
- try {
- i = Integer.parseInt(weight);
- } catch (NumberFormatException e) {
- i = 0;
- }
-
- if (i > 600)
- weight = "bold";
- else if (i > 0)
- weight = "normal";
-
- return family + "," + style + "," + weight;
+ public static String createFontKey(String family, String style,
+ String weight) {
+ int i;
+
+ try {
+ i = Integer.parseInt(weight);
+ } catch (NumberFormatException e) {
+ i = 0;
+ }
+
+ if (i > 600)
+ weight = "bold";
+ else if (i > 0)
+ weight = "normal";
+
+ return family + "," + style + "," + weight;
}
-
-
- public Hashtable getFonts() {
- return this.fonts;
- }
+ public Hashtable getFonts() {
+ return this.fonts;
+ }
- public Hashtable getUsedFonts() {
- return this.usedFonts;
- }
+ public Hashtable getUsedFonts() {
+ return this.usedFonts;
+ }
- public FontMetric getMetricsFor(String fontName) throws FOPException {
- usedFonts.put(fontName, fonts.get(fontName));
- return (FontMetric)fonts.get(fontName);
- }
+ public FontMetric getMetricsFor(String fontName) throws FOPException {
+ usedFonts.put(fontName, fonts.get(fontName));
+ return (FontMetric) fonts.get(fontName);
+ }
}
package org.apache.fop.svg;
import java.awt.Graphics2D;
-import java.awt.Shape;
+import java.awt.*;
import java.text.AttributedCharacterIterator;
import java.awt.font.FontRenderContext;
import java.awt.geom.Point2D;
import java.awt.geom.Rectangle2D;
+import java.awt.Font;
import java.text.AttributedCharacterIterator;
import java.text.AttributedString;
import java.text.CharacterIterator;
import java.awt.font.TextLayout;
+import java.awt.font.TextAttribute;
import java.util.ArrayList;
import java.util.HashSet;
-import java.util.List;
+import java.util.*;
+import java.util.Set;
import org.apache.batik.gvt.text.Mark;
import org.apache.batik.gvt.*;
import org.apache.batik.gvt.text.*;
import org.apache.batik.gvt.renderer.*;
+import org.apache.batik.gvt.font.*;
import org.apache.fop.layout.*;
* @version $Id$
*/
public class PDFTextPainter implements TextPainter {
-FontState fontState;
+ FontState fontState;
-public PDFTextPainter(FontState fs)
-{
-fontState = fs;
-}
+ public PDFTextPainter(FontState fs) {
+ fontState = fs;
+ }
/**
* Paints the specified attributed character iterator using the
* @param g2d the Graphics2D to use
* @param context the rendering context.
*/
- public void paint(TextNode node,
- Graphics2D g2d,
- GraphicsNodeRenderContext context)
- {
-System.out.println("PDFText paint");
-String txt = node.getText();
-Point2D loc = node.getLocation();
-g2d.drawString(txt, (float)loc.getX(), (float)loc.getY());
-}
+ public void paint(TextNode node, Graphics2D g2d,
+ GraphicsNodeRenderContext context) {
+ System.out.println("PDFText paint");
+ String txt = node.getText();
+ Point2D loc = node.getLocation();
+
+ AttributedCharacterIterator aci =
+ node.getAttributedCharacterIterator();
+ // reset position to start of char iterator
+ aci.first();
+ TextNode.Anchor anchor = (TextNode.Anchor) aci.getAttribute(
+ GVTAttributedCharacterIterator.TextAttribute.ANCHOR_TYPE);
+
+ Vector gvtFonts = (Vector) aci.getAttribute(
+ GVTAttributedCharacterIterator.TextAttribute.GVT_FONT_FAMILIES);
+ Paint forg = (Paint) aci.getAttribute(TextAttribute.FOREGROUND);
+ Float size = (Float) aci.getAttribute(TextAttribute.SIZE);
+ Stroke stroke = (Stroke) aci.getAttribute(
+ GVTAttributedCharacterIterator.TextAttribute.STROKE);
+ Float xpos = (Float) aci.getAttribute(
+ GVTAttributedCharacterIterator.TextAttribute.X);
+ Float ypos = (Float) aci.getAttribute(
+ GVTAttributedCharacterIterator.TextAttribute.Y);
+
+ Float posture = (Float) aci.getAttribute(TextAttribute.POSTURE);
+ Float taWeight = (Float) aci.getAttribute(TextAttribute.WEIGHT);
+
+ Set set = aci.getAllAttributeKeys();
+ for (Iterator iter = set.iterator(); iter.hasNext();) {
+ System.out.println(iter.next());
+ }
+
+ if (forg instanceof Color) {
+ g2d.setColor((Color) forg);
+ }
+ g2d.setPaint(forg);
+ g2d.setStroke(stroke);
+
+ String style = posture.floatValue() > 0.0 ? "italic" : "normal";
+ String weight = taWeight.floatValue() > 1.0 ? "bold" : "normal";
+
+ FontInfo fi = fontState.getFontInfo();
+ boolean found = false;
+ for (Enumeration e = gvtFonts.elements(); e.hasMoreElements();) {
+ GVTFontFamily fam = (GVTFontFamily) e.nextElement();
+ String name = fam.getFamilyName();
+ System.out.println(name);
+ if (fi.hasFont(name, weight, style)) {
+ try {
+ int fsize = (int) size.floatValue();
+ fontState = new FontState(fontState.getFontInfo(),
+ name, style, weight, fsize * 1000, 0);
+ } catch (org.apache.fop.apps.FOPException fope) {
+ fope.printStackTrace();
+ }
+ found = true;
+ break;
+ }
+ }
+ if (!found) {
+ try {
+ int fsize = (int) size.floatValue();
+ fontState = new FontState(fontState.getFontInfo(), "any",
+ style, weight, fsize * 1000, 0);
+ } catch (org.apache.fop.apps.FOPException fope) {
+ fope.printStackTrace();
+ }
+ }
+ int fStyle = Font.PLAIN;
+ if (fontState.getFontWeight().equals("bold")) {
+ if (fontState.getFontStyle().equals("italic")) {
+ fStyle = Font.BOLD | Font.ITALIC;
+ } else {
+ fStyle = Font.BOLD;
+ }
+ } else {
+ if (fontState.getFontStyle().equals("italic")) {
+ fStyle = Font.ITALIC;
+ } else {
+ fStyle = Font.PLAIN;
+ }
+ }
+ Font font = new Font(fontState.getFontFamily(), fStyle,
+ (int)(fontState.getFontSize() / 1000));
+
+ g2d.setFont(font);
+
+
+ float advance = getStringWidth(txt);
+ System.out.println("ad:" + advance + " a:" + anchor + " ind:" +
+ aci.getIndex());
+ 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;
+ }
+ }
+ g2d.drawString(txt, (float)(loc.getX() + tx), (float)(loc.getY()));
+ }
+
+ public float getStringWidth(String str) {
+ float wordWidth = 0;
+ float whitespaceWidth = fontState.width(fontState.mapChar(' '));
+
+ for (int i = 0; i < str.length(); i++) {
+ float charWidth;
+ char c = str.charAt(i);
+ if (!((c == ' ') || (c == '\n') || (c == '\r') || (c == '\t'))) {
+ charWidth = fontState.width(fontState.mapChar(c));
+ if (charWidth <= 0)
+ charWidth = whitespaceWidth;
+ } else {
+ charWidth = whitespaceWidth;
+ }
+ wordWidth += charWidth;
+ }
+ return wordWidth / 1000f;
+ }
/**
* Initiates a text selection on a particular AttributedCharacterIterator,
* @return an instance of Mark which encapsulates the state necessary to
* implement hit testing and text selection.
*/
- public Mark selectAt(double x, double y, AttributedCharacterIterator aci,
- TextNode node, GraphicsNodeRenderContext context)
-{
-System.out.println("PDFText selectAt");
-return null;
-}
+ public Mark selectAt(double x, double y,
+ AttributedCharacterIterator aci, TextNode node,
+ GraphicsNodeRenderContext context) {
+ System.out.println("PDFText selectAt");
+ return null;
+ }
/**
* Continues a text selection on a particular AttributedCharacterIterator,
* implement hit testing and text selection.
*/
public Mark selectTo(double x, double y, Mark beginMark,
- AttributedCharacterIterator aci,
- TextNode node, GraphicsNodeRenderContext context)
-{
-System.out.println("PDFText selectTo");
-return null;
-}
+ AttributedCharacterIterator aci, TextNode node,
+ GraphicsNodeRenderContext context) {
+ System.out.println("PDFText selectTo");
+ return null;
+ }
/**
* Select all of the text represented by an AttributedCharacterIterator,
* implement hit testing and text selection.
*/
public Mark selectAll(double x, double y,
- AttributedCharacterIterator aci,
- TextNode node, GraphicsNodeRenderContext context)
-{
-System.out.println("PDFText selectAll");
-return null;
-}
+ AttributedCharacterIterator aci, TextNode node,
+ GraphicsNodeRenderContext context) {
+ System.out.println("PDFText selectAll");
+ return null;
+ }
/**
* Selects the first glyph in the text node.
*/
public Mark selectFirst(double x, double y,
- AttributedCharacterIterator aci,
- TextNode node,
- GraphicsNodeRenderContext context)
-{
-System.out.println("PDFText selectFirst");
-return null;
-}
+ AttributedCharacterIterator aci, TextNode node,
+ GraphicsNodeRenderContext context) {
+ System.out.println("PDFText selectFirst");
+ return null;
+ }
/**
* Selects the last glyph in the text node.
*/
public Mark selectLast(double x, double y,
- AttributedCharacterIterator aci,
- TextNode node,
- GraphicsNodeRenderContext context)
-{
-System.out.println("PDFText selectLast");
-return null;
-}
+ AttributedCharacterIterator aci, TextNode node,
+ GraphicsNodeRenderContext context) {
+ System.out.println("PDFText selectLast");
+ return null;
+ }
/*
* Get an array of index pairs corresponding to the indices within an
* implementation details of its own Mark implementation.
*/
public int[] getSelected(AttributedCharacterIterator aci,
- Mark start, Mark finish)
-{
-System.out.println("PDFText getSelected");
-return null;
-}
+ Mark start, Mark finish) {
+ System.out.println("PDFText getSelected");
+ return null;
+ }
/*
* selectTo(), since the TextPainter implementation may rely on hidden
* implementation details of its own Mark implementation.
*/
- public Shape getHighlightShape(Mark beginMark, Mark endMark)
-{
-System.out.println("PDFText getHighlightShape");
-return null;
-}
+ public Shape getHighlightShape(Mark beginMark, Mark endMark) {
+ System.out.println("PDFText getHighlightShape");
+ return null;
+ }
/*
* Get a Shape in userspace coords which defines the textnode glyph outlines.
* @param includeStroke whether to create the "stroke shape outlines"
* instead of glyph outlines.
*/
- public Shape getShape(TextNode node, FontRenderContext frc)
-{
-System.out.println("PDFText getShape");
-return null;
-}
+ public Shape getShape(TextNode node, FontRenderContext frc) {
+ System.out.println("PDFText getShape");
+ return null;
+ }
/*
* Get a Shape in userspace coords which defines the textnode glyph outlines.
* @param includeStroke whether to create the "stroke shape outlines"
* instead of glyph outlines.
*/
- public Shape getDecoratedShape(TextNode node, FontRenderContext frc)
-{
-System.out.println("PDFText getDecoratedShape");
-return null;
-}
+ public Shape getDecoratedShape(TextNode node, FontRenderContext frc) {
+ System.out.println("PDFText getDecoratedShape");
+ return new Rectangle(1, 1);
+ }
/*
* Get a Rectangle2D in userspace coords which encloses the textnode
* @param g2d the Graphics2D to use
* @param context rendering context.
*/
- public Rectangle2D getBounds(TextNode node,
- FontRenderContext frc)
-{
-System.out.println("PDFText getBounds");
-return null;
-}
+ public Rectangle2D getBounds(TextNode node, FontRenderContext frc) {
+ System.out.println("PDFText getBounds");
+ return null;
+ }
/*
* Get a Rectangle2D in userspace coords which encloses the textnode
* @param g2d the Graphics2D to use
* @param context rendering context.
*/
- public Rectangle2D getDecoratedBounds(TextNode node,
- FontRenderContext frc)
-{
-System.out.println("PDFText getDecoratedBounds");
-return null;
-}
+ public Rectangle2D getDecoratedBounds(TextNode node,
+ FontRenderContext frc) {
+ System.out.println("PDFText getDecoratedBounds");
+ return null;
+ }
/*
* Get a Rectangle2D in userspace coords which encloses the
* @param g2d the Graphics2D to use
* @param context rendering context.
*/
- public Rectangle2D getPaintedBounds(TextNode node,
- FontRenderContext frc)
-{
-System.out.println("PDFText getPaintedBounds");
-return null;
-}
-
-
+ public Rectangle2D getPaintedBounds(TextNode node,
+ FontRenderContext frc) {
+ System.out.println("PDFText getPaintedBounds");
+ return null;
+ }
}