/* * $Id$ * Copyright (C) 2001 The Apache Software Foundation. All rights reserved. * For details on use and redistribution please refer to the * LICENSE file included with these sources. */ package org.apache.fop.svg; import java.awt.Graphics2D; import java.awt.*; import java.text.AttributedCharacterIterator; 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.*; 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.*; /** * Renders the attributed character iterator of a TextNode. * * @author Keiron Liddle * @version $Id$ */ public class PDFTextPainter implements TextPainter { FontInfo fontInfo; protected final static TextPainter proxyPainter = StrokingTextPainter.getInstance(); public PDFTextPainter(FontInfo fi) { fontInfo = fi; } /** * Paints the specified attributed character iterator using the * specified Graphics2D and context and font context. * @param node the TextNode to paint * @param g2d the Graphics2D to use * @param context the rendering context. */ public void paint(TextNode node, Graphics2D g2d) { // System.out.println("PDFText paint"); String txt = node.getText(); Point2D loc = node.getLocation(); AttributedCharacterIterator aci = node.getAttributedCharacterIterator(); // reset position to start of char iterator if (aci.getBeginIndex() == aci.getEndIndex()) { return; } char ch = aci.first(); if (ch == AttributedCharacterIterator.DONE) { return; } 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); Paint strokePaint = (Paint)aci.getAttribute(GVTAttributedCharacterIterator.TextAttribute.STROKE_PAINT); Float size = (Float)aci.getAttribute(TextAttribute.SIZE); if(size == null) { return; } 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); boolean useStrokePainter = false; if (forg instanceof Color) { Color col = (Color)forg; if(col.getAlpha() != 255) { useStrokePainter = true; } g2d.setColor(col); } g2d.setPaint(forg); g2d.setStroke(stroke); if(strokePaint != null) { // need to draw using AttributedCharacterIterator useStrokePainter = true; } if(useStrokePainter) { proxyPainter.paint(node, g2d); return; } String style = ((posture != null) && (posture.floatValue() > 0.0)) ? "italic" : "normal"; int weight = ((taWeight != null) && (taWeight.floatValue() > 1.0)) ? FontInfo.BOLD : FontInfo.NORMAL; FontState fontState = null; FontInfo fi = fontInfo; boolean found = false; String fontFamily = null; if (gvtFonts != null) { for (Enumeration e = gvtFonts.elements(); e.hasMoreElements(); ) { GVTFontFamily fam = (GVTFontFamily)e.nextElement(); fontFamily = fam.getFamilyName(); if (fi.hasFont(fontFamily, style, weight)) { String fname = fontInfo.fontLookup(fontFamily, style, weight); FontMetric metrics = fontInfo.getMetricsFor(fname); int fsize = (int)(size.floatValue() * 1000); fontState = new FontState(fname, metrics, fsize); found = true; break; } } } if (!found) { String fname = fontInfo.fontLookup("any", style, FontInfo.NORMAL); FontMetric metrics = fontInfo.getMetricsFor(fname); int fsize = (int)(size.floatValue() * 1000); fontState = new FontState(fname, metrics, fsize); } else { if(g2d instanceof PDFGraphics2D) { ((PDFGraphics2D)g2d).setOverrideFontState(fontState); } } int fStyle = Font.PLAIN; if (weight == FontInfo.BOLD) { if (style.equals("italic")) { fStyle = Font.BOLD | Font.ITALIC; } else { fStyle = Font.BOLD; } } else { if (style.equals("italic")) { fStyle = Font.ITALIC; } else { fStyle = Font.PLAIN; } } Font font = new Font(fontFamily, fStyle, (int)(fontState.getFontSize() / 1000)); g2d.setFont(font); float advance = getStringWidth(txt, fontState); 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, FontState fontState) { 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; } public Mark getMark(TextNode node, int pos, boolean all) { System.out.println("PDFText getMark"); return null; } public Mark selectAt(double x, double y, TextNode node) { System.out.println("PDFText selectAt"); return null; } public Mark selectTo(double x, double y, Mark beginMark) { System.out.println("PDFText selectTo"); return null; } public Mark selectAll(double x, double y, TextNode node) { System.out.println("PDFText selectAll"); return null; } public Mark selectFirst(TextNode node) { System.out.println("PDFText selectFirst"); return null; } public Mark selectLast(TextNode node) { System.out.println("PDFText selectLast"); return null; } public int[] getSelected(Mark start, Mark finish) { System.out.println("PDFText getSelected"); return null; } public Shape getHighlightShape(Mark beginMark, Mark endMark) { System.out.println("PDFText getHighlightShape"); return null; } public Shape getShape(TextNode node) { System.out.println("PDFText getShape"); return proxyPainter.getShape(node); } public Shape getDecoratedShape(TextNode node) { //System.out.println("PDFText getDecoratedShape"); return proxyPainter.getDecoratedShape(node); } public Rectangle2D getBounds(TextNode node) { //System.out.println("PDFText getBounds"); return proxyPainter.getBounds(node); } public Rectangle2D getDecoratedBounds(TextNode node) { System.out.println("PDFText getDecoratedBounds"); return proxyPainter.getDecoratedBounds(node); } public Rectangle2D getPaintedBounds(TextNode node) { // System.out.println("PDFText getPaintedBounds"); return proxyPainter.getPaintedBounds(node); } }