/** Currently valid FontState */
protected FontState fontState;
-
+
+ /** Overriding FontState */
+ protected FontState overrideFontState = null;
+
/**
* the current (internal) font name
*/
Shape imclip = getClip();
writeClip(imclip);
Color c = getColor();
- gen.writeln(c.getRed() + " " + c.getGreen() + " " + c.getBlue()
- + " setrgbcolor");
+ gen.writeln(gen.formatDouble(c.getRed() / 255.0) + " "
+ + gen.formatDouble(c.getGreen() / 255.0) + " "
+ + gen.formatDouble(c.getBlue() / 255.0) + " setrgbcolor");
applyPaint(getPaint(), false);
applyStroke(getStroke());
+ " M");
break;
case PathIterator.SEG_QUADTO:
- // psRenderer.write((1000 * PDFNumber.doubleOut(vals[0])) +
- // " " + (1000 * PDFNumber.doubleOut(vals[1])) + " " +
- // (1000 * PDFNumber.doubleOut(vals[2])) + " " +
- // (1000 * PDFNumber.doubleOut(vals[3])) + " y\n");
+ gen.writeln(gen.formatDouble(1000 * vals[0]) + " "
+ + gen.formatDouble(1000 * vals[1]) + " "
+ + gen.formatDouble(1000 * vals[2]) + " "
+ + gen.formatDouble(1000 * vals[3]) + " QUADTO ");
break;
case PathIterator.SEG_CLOSE:
gen.writeln("closepath");
+ " M");
break;
case PathIterator.SEG_QUADTO:
- // psRenderer.write(1000 * PDFNumber.doubleOut(vals[0]) +
- // " " + 1000 * PDFNumber.doubleOut(vals[1]) + " " +
- // 1000 * PDFNumber.doubleOut(vals[2]) + " " +
- // 1000 * PDFNumber.doubleOut(vals[3]) + " y\n");
+ gen.writeln(gen.formatDouble(1000 * vals[0]) + " "
+ + gen.formatDouble(1000 * vals[1]) + " "
+ + gen.formatDouble(1000 * vals[2]) + " "
+ + gen.formatDouble(1000 * vals[3]) + " QUADTO ");
break;
case PathIterator.SEG_CLOSE:
gen.writeln("closepath");
* @see #setClip
*/
public void drawString(String s, float x, float y) {
- try {
- System.out.println("drawString(String)");
- gen.writeln("BT");
- Shape imclip = getClip();
- writeClip(imclip);
- Color c = getColor();
- gen.writeln(c.getRed() + " " + c.getGreen() + " " + c.getBlue()
- + " setrgbcolor");
-
- AffineTransform trans = getTransform();
- trans.translate(x, y);
- double[] vals = new double[6];
- trans.getMatrix(vals);
-
- gen.writeln(gen.formatDouble(vals[0]) + " "
- + gen.formatDouble(vals[1]) + " "
- + gen.formatDouble(vals[2]) + " "
- + gen.formatDouble(vals[3]) + " "
- + gen.formatDouble(vals[4]) + " "
- + gen.formatDouble(vals[5]) + " "
- + gen.formatDouble(vals[6]) + " Tm [" + s + "]");
+ try {
+ if (overrideFontState == null) {
+ Font gFont = getFont();
+ String n = gFont.getFamily();
+ if (n.equals("sanserif")) {
+ n = "sans-serif";
+ }
+ int siz = gFont.getSize();
+ String style = gFont.isItalic() ? "italic" : "normal";
+ String weight = gFont.isBold() ? "bold" : "normal";
- gen.writeln("ET");
- } catch (IOException ioe) {
- handleIOException(ioe);
+ //try {
+ //fontState = new FontState(n, fontState.getFontMetrics(),siz);
+ //} catch (org.apache.fop.apps.FOPException fope) {
+ //fope.printStackTrace();
+ //}
+ } else {
+ fontState = overrideFontState;
+ overrideFontState = null;
+ }
+ Shape imclip = getClip();
+ writeClip(imclip);
+ Color c = getColor();
+ gen.writeln(c.getRed() / 255.0 + " "
+ + c.getGreen() / 255.0 + " "
+ + c.getBlue() / 255.0 + " setrgbcolor");
+
+ AffineTransform trans = getTransform();
+ trans.translate(x, y);
+ double[] vals = new double[6];
+ trans.getMatrix(vals);
+ gen.writeln(gen.formatDouble(1000 * vals[4]) + " "
+ + gen.formatDouble(1000 * vals[5]) + " moveto ");
+ //String fontWeight = fontState.getFontWeight();
+ StringBuffer sb = new StringBuffer();
+
+ int l = s.length();
+
+ if ((currentFontName != fontState.getFontName())
+ || (currentFontSize != fontState.getFontSize())) {
+ gen.writeln(fontState.getFontName() + " " + fontState.getFontSize() + " F");
+ currentFontName = fontState.getFontName();
+ currentFontSize = fontState.getFontSize();
}
+ for (int i = 0; i < l; i++) {
+ char ch = s.charAt(i);
+ char mch = fontState.mapChar(ch);
+ if (mch > 127) {
+ sb = sb.append("\\" + Integer.toOctalString(mch));
+ } else {
+ String escape = "\\()[]{}";
+ if (escape.indexOf(mch) >= 0) {
+ sb.append("\\");
+ }
+ sb = sb.append(mch);
+ }
+ }
+
+ String psString = null;
+ psString = " (" + sb.toString() + ") " + " t ";
+
+ gen.writeln(" 1.0 -1.0 scale");
+ gen.writeln(psString);
+ gen.writeln(" 1.0 -1.0 scale");
+ } catch (IOException ioe) {
+ handleIOException(ioe);
+ }
}
/**
Shape imclip = getClip();
writeClip(imclip);
Color c = getColor();
- gen.writeln(c.getRed() + " " + c.getGreen() + " " + c.getBlue()
- + " setrgbcolor");
+ gen.writeln(gen.formatDouble(c.getRed() / 255.0) + " "
+ + gen.formatDouble(c.getGreen() / 255.0) + " "
+ + gen.formatDouble(c.getBlue() / 255.0) + " setrgbcolor");
applyPaint(getPaint(), true);
+ " M");
break;
case PathIterator.SEG_QUADTO:
- // psRenderer.write(1000 * PDFNumber.doubleOut(vals[0]) +
- // " " + 1000 * PDFNumber.doubleOut(vals[1]) + " " +
- // 1000 * PDFNumber.doubleOut(vals[2]) + " " +
- // 1000 * PDFNumber.doubleOut(vals[3]) + " y\n");
+ gen.writeln(gen.formatDouble(1000 * vals[0]) + " "
+ + gen.formatDouble(1000 * vals[1]) + " "
+ + gen.formatDouble(1000 * vals[2]) + " "
+ + gen.formatDouble(1000 * vals[3]) + " QUADTO ");
break;
case PathIterator.SEG_CLOSE:
gen.writeln("closepath");
fmg = bi.createGraphics();
}
+ /**
+ * Sets the overrideing font state.
+ * @param infont FontState to set
+ */
+ public void setOverrideFontState(FontState infont) {
+ overrideFontState = infont;
+ }
+
/**
* Gets the font metrics for the specified font.
* @return the font metrics for the specified font.
gen.writeln(" Tt setlinewidth stroke");
gen.writeln(" grestore");
gen.writeln("} bd");
-
+
+ gen.writeln("/QUADTO {");
+ gen.writeln("/Y22 exch store");
+ gen.writeln("/X22 exch store");
+ gen.writeln("/Y21 exch store");
+ gen.writeln("/X21 exch store");
+ gen.writeln("currentpoint");
+ gen.writeln("/Y21 load 2 mul add 3 div exch");
+ gen.writeln("/X21 load 2 mul add 3 div exch");
+ gen.writeln("/X21 load 2 mul /X22 load add 3 div");
+ gen.writeln("/Y21 load 2 mul /Y22 load add 3 div");
+ gen.writeln("/X22 load /Y22 load curveto");
+ gen.writeln("} bd");
+
gen.writeln("%%EndResource");
}
import java.util.Map;
// FOP
+import org.apache.fop.fo.properties.BackgroundRepeat;
+import org.apache.fop.area.Area;
+import org.apache.fop.area.RegionViewport;
import org.apache.fop.apps.FOPException;
import org.apache.fop.area.Block;
import org.apache.fop.area.BlockViewport;
import org.apache.fop.layout.FontInfo;
import org.apache.fop.render.AbstractRenderer;
import org.apache.fop.render.RendererContext;
-import org.w3c.dom.Document;
+import org.apache.fop.image.FopImage;
+import org.apache.fop.image.ImageFactory;
+import org.apache.fop.traits.BorderProps;
+import org.w3c.dom.Document;
/**
* Renderer that renders to PostScript.
* <br>
{page.getPageNumber(),
new Integer(this.currentPageNumber)});
final Integer zero = new Integer(0);
- final Long pagewidth = new Long(Math.round(page.getViewArea().getWidth() / 1000f));
- final Long pageheight = new Long(Math.round(page.getViewArea().getHeight() / 1000f));
+ final Long pagewidth = new Long(Math.round(page.getViewArea().getWidth()));
+ final Long pageheight = new Long(Math.round(page.getViewArea().getHeight()));
gen.writeDSCComment(DSCConstants.PAGE_BBOX, new Object[]
{zero, zero, pagewidth, pageheight});
gen.writeDSCComment(DSCConstants.BEGIN_PAGE_SETUP);
gen.writeln("FOPFonts begin");
- concatMatrix(1, 0, 0, -1, 0, pageheight.doubleValue());
gen.writeln("0.001 0.001 scale");
+ concatMatrix(1, 0, 0, -1, 0, pageheight.doubleValue());
+
gen.writeDSCComment(DSCConstants.END_PAGE_SETUP);
//Process page
saveGraphicsState();
// multiply with current CTM
- //currentStream.add(CTMHelper.toPDFString(ctm) + " cm\n");
+ //writeln(CTMHelper.toPDFString(ctm) + " cm\n");
final double matrix[] = ctm.toArray();
concatMatrix(matrix);
//currentState.pop();
}
+ /**
+ * Handle the viewport traits.
+ * This is used to draw the traits for a viewport.
+ *
+ * @param region the viewport region to handle
+ */
+ protected void handleViewportTraits(RegionViewport region) {
+ currentFontName = "";
+ float startx = 0;
+ float starty = 0;
+ Rectangle2D viewArea = region.getViewArea();
+ float width = (float)(viewArea.getWidth());
+ float height = (float)(viewArea.getHeight());
+ /*
+ Trait.Background back;
+ back = (Trait.Background)region.getTrait(Trait.BACKGROUND);
+ */
+ drawBackAndBorders(region, startx, starty, width, height);
+ }
+
+ /**
+ * Handle block traits.
+ * The block could be any sort of block with any positioning
+ * so this should render the traits such as border and background
+ * in its position.
+ *
+ * @param block the block to render the traits
+ */
+ protected void handleBlockTraits(Block block) {
+ float startx = currentIPPosition;
+ float starty = currentBPPosition;
+ drawBackAndBorders(block, startx, starty,
+ block.getWidth(), block.getHeight());
+ }
+
+ /**
+ * Draw the background and borders.
+ * This draws the background and border traits for an area given
+ * the position.
+ *
+ * @param block the area to get the traits from
+ * @param startx the start x position
+ * @param starty the start y position
+ * @param width the width of the area
+ * @param height the height of the area
+ */
+ protected void drawBackAndBorders(Area block,
+ float startx, float starty,
+ float width, float height) {
+ // draw background then border
+
+ boolean started = false;
+ Trait.Background back;
+ back = (Trait.Background)block.getTrait(Trait.BACKGROUND);
+ if (back != null) {
+ started = true;
+// closeText();
+ endTextObject();
+ //saveGraphicsState();
+
+ if (back.getColor() != null) {
+ updateColor(back.getColor(), true, null);
+ writeln(startx + " " + starty + " "
+ + width + " " + height + " rectfill");
+ }
+ if (back.getURL() != null) {
+ ImageFactory fact = ImageFactory.getInstance();
+ FopImage fopimage = fact.getImage(back.getURL(), userAgent);
+ if (fopimage != null && fopimage.load(FopImage.DIMENSIONS, userAgent)) {
+ if (back.getRepeat() == BackgroundRepeat.REPEAT) {
+ // create a pattern for the image
+ } else {
+ // place once
+ Rectangle2D pos;
+ pos = new Rectangle2D.Float((startx + back.getHoriz()) * 1000,
+ (starty + back.getVertical()) * 1000,
+ fopimage.getWidth() * 1000,
+ fopimage.getHeight() * 1000);
+ // putImage(back.url, pos);
+ }
+ }
+ }
+ }
+
+ BorderProps bps = (BorderProps)block.getTrait(Trait.BORDER_BEFORE);
+ if (bps != null) {
+ float endx = startx + width;
+
+ if (!started) {
+ started = true;
+// closeText();
+ endTextObject();
+ //saveGraphicsState();
+ }
+
+ float bwidth = bps.width ;
+ updateColor(bps.color, false, null);
+ writeln(bwidth + " setlinewidth");
+
+ drawLine(startx, starty + bwidth / 2, endx, starty + bwidth / 2);
+ }
+ bps = (BorderProps)block.getTrait(Trait.BORDER_START);
+ if (bps != null) {
+ float endy = starty + height;
+
+ if (!started) {
+ started = true;
+// closeText();
+ endTextObject();
+ //saveGraphicsState();
+ }
+
+ float bwidth = bps.width ;
+ updateColor(bps.color, false, null);
+ writeln(bwidth + " setlinewidth");
+
+ drawLine(startx + bwidth / 2, starty, startx + bwidth / 2, endy);
+ }
+ bps = (BorderProps)block.getTrait(Trait.BORDER_AFTER);
+ if (bps != null) {
+ float sy = starty + height;
+ float endx = startx + width;
+
+ if (!started) {
+ started = true;
+// closeText();
+ endTextObject();
+ //saveGraphicsState();
+ }
+
+ float bwidth = bps.width ;
+ updateColor(bps.color, false, null);
+ writeln(bwidth + " setlinewidth");
+
+ drawLine(startx, sy - bwidth / 2, endx, sy - bwidth / 2);
+ }
+ bps = (BorderProps)block.getTrait(Trait.BORDER_END);
+ if (bps != null) {
+ float sx = startx + width;
+ float endy = starty + height;
+
+ if (!started) {
+ started = true;
+ // closeText();
+ endTextObject();
+ //saveGraphicsState();
+ }
+
+ float bwidth = bps.width ;
+ updateColor(bps.color, false, null);
+ writeln(bwidth + " setlinewidth");
+ drawLine(sx - bwidth / 2, starty, sx - bwidth / 2, endy);
+ }
+ if (started) {
+ //restoreGraphicsState();
+ beginTextObject();
+ // font last set out of scope in text section
+ currentFontName = "";
+ }
+ }
+
+ /**
+ * Draw a line.
+ *
+ * @param startx the start x position
+ * @param starty the start y position
+ * @param endx the x end position
+ * @param endy the y end position
+ */
+ private void drawLine(float startx, float starty, float endx, float endy) {
+ writeln(startx + " " + starty + " M ");
+ writeln(endx + " " + endy + " lineto");
+ }
+ private void updateColor(ColorType col, boolean fill, StringBuffer pdf) {
+ writeln(gen.formatDouble(col.getRed()) + " "
+ + gen.formatDouble(col.getGreen()) + " "
+ + gen.formatDouble(col.getBlue()) + " setrgbcolor");
+ }
+
+ private void updateFont(String name, int size, StringBuffer pdf) {
+
+ }
+
/**
* @see org.apache.fop.render.AbstractRenderer#renderForeignObject(ForeignObject, Rectangle2D)
*/
new Integer(currentBlockIPPosition + (int) pos.getX()));
context.setProperty(PSXMLHandler.PS_YPOS,
new Integer(currentBPPosition + (int) pos.getY()));
+ //context.setProperty("strokeSVGText", options.get("strokeSVGText"));
+
/*
context.setProperty(PDFXMLHandler.PDF_DOCUMENT, pdfDoc);
context.setProperty(PDFXMLHandler.OUTPUT_STREAM, ostream);
--- /dev/null
+/*
+ * $Id$
+ * ============================================================================
+ * The Apache Software License, Version 1.1
+ * ============================================================================
+ *
+ * Copyright (C) 1999-2003 The Apache Software Foundation. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without modifica-
+ * tion, are permitted provided that the following conditions are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright notice,
+ * this list of conditions and the following disclaimer.
+ *
+ * 2. Redistributions in binary form must reproduce the above copyright notice,
+ * this list of conditions and the following disclaimer in the documentation
+ * and/or other materials provided with the distribution.
+ *
+ * 3. The end-user documentation included with the redistribution, if any, must
+ * include the following acknowledgment: "This product includes software
+ * developed by the Apache Software Foundation (http://www.apache.org/)."
+ * Alternately, this acknowledgment may appear in the software itself, if
+ * and wherever such third-party acknowledgments normally appear.
+ *
+ * 4. The names "FOP" and "Apache Software Foundation" must not be used to
+ * endorse or promote products derived from this software without prior
+ * written permission. For written permission, please contact
+ * apache@apache.org.
+ *
+ * 5. Products derived from this software may not be called "Apache", nor may
+ * "Apache" appear in their name, without prior written permission of the
+ * Apache Software Foundation.
+ *
+ * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED WARRANTIES,
+ * INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
+ * FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
+ * APACHE SOFTWARE FOUNDATION OR ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT,
+ * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLU-
+ * DING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS
+ * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
+ * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
+ * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ * ============================================================================
+ *
+ * This software consists of voluntary contributions made by many individuals
+ * on behalf of the Apache Software Foundation and was originally created by
+ * James Tauber <jtauber@jtauber.com>. For more information on the Apache
+ * Software Foundation, please see <http://www.apache.org/>.
+ */
+package org.apache.fop.render.ps;
+
+import java.awt.Graphics2D;
+import java.awt.geom.Point2D;
+import java.awt.geom.Rectangle2D;
+import java.awt.Font;
+
+import java.text.AttributedCharacterIterator;
+import java.awt.font.TextAttribute;
+import java.awt.Shape;
+import java.awt.Paint;
+import java.awt.Stroke;
+import java.awt.Color;
+import java.util.List;
+import java.util.Iterator;
+
+import org.apache.batik.gvt.text.Mark;
+import org.apache.batik.gvt.TextPainter;
+import org.apache.batik.gvt.TextNode;
+import org.apache.batik.gvt.text.GVTAttributedCharacterIterator;
+import org.apache.batik.gvt.font.GVTFontFamily;
+import org.apache.batik.bridge.SVGFontFamily;
+import org.apache.batik.gvt.renderer.StrokingTextPainter;
+
+import org.apache.fop.fonts.FontMetrics;
+import org.apache.fop.layout.FontState;
+import org.apache.fop.layout.FontInfo;
+
+/**
+ * Renders the attributed character iterator of a <tt>TextNode</tt>.
+ * This class draws the text directly into the PSGraphics2D so that
+ * the text is not drawn using shapes which makes the PS files larger.
+ * If the text is simple enough to draw then it sets the font and calls
+ * drawString. If the text is complex or the cannot be translated
+ * into a simple drawString the StrokingTextPainter is used instead.
+ *
+ * @todo handle underline, overline and strikethrough
+ * @todo use drawString(AttributedCharacterIterator iterator...) for some
+ *
+ * @author <a href="mailto:keiron@aftexsw.com">Keiron Liddle</a>
+ * @version $Id: PSTextPainter.java,v 1.15 2003/01/08 14:03:55 jeremias Exp $
+ */
+public class PSTextPainter implements TextPainter {
+ private FontInfo fontInfo;
+
+ /**
+ * 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();
+
+ /**
+ * Create a new PS text painter with the given font information.
+ * @param fi the fint info
+ */
+ public PSTextPainter(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
+ */
+ public void paint(TextNode node, Graphics2D g2d) {
+ // System.out.println("PSText 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;
+ anchor = (TextNode.Anchor) aci.getAttribute(
+ GVTAttributedCharacterIterator.TextAttribute.ANCHOR_TYPE);
+
+ List gvtFonts;
+ gvtFonts = (List) aci.getAttribute(
+ GVTAttributedCharacterIterator.TextAttribute.GVT_FONT_FAMILIES);
+ Paint forg = (Paint) aci.getAttribute(TextAttribute.FOREGROUND);
+ Paint strokePaint;
+ 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 (hasUnsupportedAttributes(aci)) {
+ useStrokePainter = true;
+ }
+
+ // text contains unsupported information
+ if (useStrokePainter) {
+ PROXY_PAINTER.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) {
+ Iterator i = gvtFonts.iterator();
+ while (i.hasNext()) {
+ GVTFontFamily fam = (GVTFontFamily) i.next();
+ if (fam instanceof SVGFontFamily) {
+ PROXY_PAINTER.paint(node, g2d);
+ return;
+ }
+ fontFamily = fam.getFamilyName();
+ if (fi.hasFont(fontFamily, style, weight)) {
+ String fname = fontInfo.fontLookup(fontFamily, style,
+ weight);
+ FontMetrics 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);
+ FontMetrics metrics = fontInfo.getMetricsFor(fname);
+ int fsize = (int)(size.floatValue() * 1000);
+ fontState = new FontState(fname, metrics, fsize);
+ } else {
+ if (g2d instanceof PSGraphics2D) {
+ ((PSGraphics2D) 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()));
+ }
+
+ private boolean hasUnsupportedAttributes(AttributedCharacterIterator aci) {
+ boolean hasunsupported = false;
+ Object letSpace = aci.getAttribute(
+ GVTAttributedCharacterIterator.TextAttribute.LETTER_SPACING);
+ if (letSpace != null) {
+ hasunsupported = true;
+ }
+
+ Object wordSpace = aci.getAttribute(
+ GVTAttributedCharacterIterator.TextAttribute.WORD_SPACING);
+ if (wordSpace != null) {
+ hasunsupported = true;
+ }
+
+ AttributedCharacterIterator.Attribute key;
+ key = GVTAttributedCharacterIterator.TextAttribute.WRITING_MODE;
+ Object writeMod = aci.getAttribute(key);
+ if (!GVTAttributedCharacterIterator.TextAttribute.WRITING_MODE_LTR.equals(
+ writeMod)) {
+ hasunsupported = true;
+ }
+
+ Object vertOr = aci.getAttribute(
+ GVTAttributedCharacterIterator.TextAttribute.VERTICAL_ORIENTATION);
+ if (GVTAttributedCharacterIterator.TextAttribute.ORIENTATION_ANGLE.equals(
+ vertOr)) {
+ hasunsupported = true;
+ }
+ return hasunsupported;
+ }
+
+ private float getStringWidth(String str, FontState fontState) {
+ float wordWidth = 0;
+ float whitespaceWidth = fontState.getWidth(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.getWidth(fontState.mapChar(c));
+ if (charWidth <= 0) {
+ charWidth = whitespaceWidth;
+ }
+ } else {
+ charWidth = whitespaceWidth;
+ }
+ wordWidth += charWidth;
+ }
+ return wordWidth / 1000f;
+ }
+
+ /**
+ * Get the outline shape of the text characters.
+ * This uses the StrokingTextPainter to get the outline
+ * shape since in theory it should be the same.
+ *
+ * @param node the text node
+ * @return the outline shape of the text characters
+ */
+ public Shape getOutline(TextNode node) {
+ return PROXY_PAINTER.getOutline(node);
+ }
+
+ /**
+ * Get the bounds.
+ * This uses the StrokingTextPainter to get the bounds
+ * since in theory it should be the same.
+ *
+ * @param node the text node
+ * @return the bounds of the text
+ */
+ public Rectangle2D getBounds2D(TextNode node) {
+ return PROXY_PAINTER.getBounds2D(node);
+ }
+
+ /**
+ * Get the geometry bounds.
+ * This uses the StrokingTextPainter to get the bounds
+ * since in theory it should be the same.
+ * @param node the text node
+ * @return the bounds of the text
+ */
+ public Rectangle2D getGeometryBounds(TextNode node) {
+ return PROXY_PAINTER.getGeometryBounds(node);
+ }
+
+ // Methods that have no purpose for PS
+
+ /**
+ * Get the mark.
+ * This does nothing since the output is pdf and not interactive.
+ * @param node the text node
+ * @param pos the position
+ * @param all select all
+ * @return null
+ */
+ public Mark getMark(TextNode node, int pos, boolean all) {
+ System.out.println("PSText getMark");
+ return null;
+ }
+
+ /**
+ * Select at.
+ * This does nothing since the output is pdf and not interactive.
+ * @param x the x position
+ * @param y the y position
+ * @param node the text node
+ * @return null
+ */
+ public Mark selectAt(double x, double y, TextNode node) {
+ System.out.println("PSText selectAt");
+ return null;
+ }
+
+ /**
+ * Select to.
+ * This does nothing since the output is pdf and not interactive.
+ * @param x the x position
+ * @param y the y position
+ * @param beginMark the start mark
+ * @return null
+ */
+ public Mark selectTo(double x, double y, Mark beginMark) {
+ System.out.println("PSText selectTo");
+ return null;
+ }
+
+ /**
+ * Selec first.
+ * This does nothing since the output is pdf and not interactive.
+ * @param node the text node
+ * @return null
+ */
+ public Mark selectFirst(TextNode node) {
+ System.out.println("PSText selectFirst");
+ return null;
+ }
+
+ /**
+ * Select last.
+ * This does nothing since the output is pdf and not interactive.
+ * @param node the text node
+ * @return null
+ */
+ public Mark selectLast(TextNode node) {
+ System.out.println("PSText selectLast");
+ return null;
+ }
+
+ /**
+ * Get selected.
+ * This does nothing since the output is pdf and not interactive.
+ * @param start the start mark
+ * @param finish the finish mark
+ * @return null
+ */
+ public int[] getSelected(Mark start, Mark finish) {
+ System.out.println("PSText getSelected");
+ return null;
+ }
+
+ /**
+ * Get the highlighted shape.
+ * This does nothing since the output is pdf and not interactive.
+ * @param beginMark the start mark
+ * @param endMark the end mark
+ * @return null
+ */
+ public Shape getHighlightShape(Mark beginMark, Mark endMark) {
+ System.out.println("PSText getHighlightShape");
+ return null;
+ }
+
+}
+
+
*/
package org.apache.fop.render.ps;
-import org.apache.fop.render.XMLHandler;
-import org.apache.fop.render.RendererContext;
-import org.apache.fop.svg.SVGUserAgent;
-import org.apache.fop.layout.FontInfo;
+// Java
+import java.awt.geom.AffineTransform;
+import java.io.IOException;
+// DOM
import org.w3c.dom.Document;
+import org.w3c.dom.svg.SVGDocument;
+import org.w3c.dom.svg.SVGSVGElement;
+// Batik
import org.apache.batik.bridge.GVTBuilder;
import org.apache.batik.bridge.BridgeContext;
import org.apache.batik.bridge.ViewBox;
-
import org.apache.batik.gvt.GraphicsNode;
+import org.apache.batik.gvt.TextPainter;
-import org.w3c.dom.svg.SVGDocument;
-import org.w3c.dom.svg.SVGSVGElement;
-
-import java.awt.geom.AffineTransform;
-import java.io.IOException;
+// FOP
+import org.apache.fop.render.XMLHandler;
+import org.apache.fop.render.RendererContext;
+import org.apache.fop.svg.SVGUserAgent;
+import org.apache.fop.layout.FontInfo;
/**
* PostScript XML handler.
transform.translate(xOffset / 1000f, yOffset / 1000f);
//aBridge.setCurrentTransform(transform);
//ctx.putBridge(aBridge);
-
+
+ TextPainter textPainter = new PSTextPainter(psInfo.getFontInfo());
+ ctx.setTextPainter(textPainter);
GraphicsNode root;
try {
root = builder.build(ctx, doc);