aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorJeremias Maerki <jeremias@apache.org>2005-08-24 20:53:55 +0000
committerJeremias Maerki <jeremias@apache.org>2005-08-24 20:53:55 +0000
commita35f808888428ef09e0c432d049b8d89e34c4880 (patch)
tree84046176c3ae26f709bd3ff9cb3f38c01a4a9193
parent1560478d80eb8a3249b230cec84f1e5242fa902b (diff)
downloadxmlgraphics-fop-a35f808888428ef09e0c432d049b8d89e34c4880.tar.gz
xmlgraphics-fop-a35f808888428ef09e0c432d049b8d89e34c4880.zip
Improved text painting for PostScript (including letter-space and word-space)
Moved text-decoration painting to the common base class and reused the border line painting method for this purpose. git-svn-id: https://svn.apache.org/repos/asf/xmlgraphics/fop/trunk@239925 13f79535-47bb-0310-9956-ffa450edef68
-rw-r--r--src/java/org/apache/fop/render/AbstractPathOrientedRenderer.java50
-rw-r--r--src/java/org/apache/fop/render/pdf/PDFRenderer.java51
-rw-r--r--src/java/org/apache/fop/render/ps/PSGenerator.java5
-rw-r--r--src/java/org/apache/fop/render/ps/PSRenderer.java152
4 files changed, 139 insertions, 119 deletions
diff --git a/src/java/org/apache/fop/render/AbstractPathOrientedRenderer.java b/src/java/org/apache/fop/render/AbstractPathOrientedRenderer.java
index 7663b5f2d..d22adb9cb 100644
--- a/src/java/org/apache/fop/render/AbstractPathOrientedRenderer.java
+++ b/src/java/org/apache/fop/render/AbstractPathOrientedRenderer.java
@@ -19,9 +19,7 @@
package org.apache.fop.render;
import java.awt.Color;
-import java.awt.geom.AffineTransform;
import java.awt.geom.Rectangle2D;
-import java.util.Iterator;
import java.util.List;
import org.apache.fop.area.Area;
@@ -30,11 +28,12 @@ import org.apache.fop.area.BlockViewport;
import org.apache.fop.area.CTM;
import org.apache.fop.area.RegionViewport;
import org.apache.fop.area.Trait;
+import org.apache.fop.area.inline.InlineArea;
import org.apache.fop.area.inline.Viewport;
import org.apache.fop.datatypes.ColorType;
+import org.apache.fop.fo.Constants;
+import org.apache.fop.fonts.Typeface;
import org.apache.fop.image.FopImage;
-import org.apache.fop.pdf.PDFState;
-import org.apache.fop.render.pdf.CTMHelper;
import org.apache.fop.traits.BorderProps;
/**
@@ -554,6 +553,49 @@ public abstract class AbstractPathOrientedRenderer extends PrintRenderer {
/** Indicates the end of a text object. */
protected abstract void endTextObject();
+ /**
+ * Paints the text decoration marks.
+ * @param tf Current typeface
+ * @param fontsize Current font size
+ * @param inline inline area to paint the marks for
+ * @param baseline position of the baseline
+ * @param startx start IPD
+ */
+ protected void renderTextDecoration(Typeface tf, int fontsize, InlineArea inline,
+ int baseline, int startx) {
+ boolean hasTextDeco = inline.hasUnderline()
+ || inline.hasOverline()
+ || inline.hasLineThrough();
+ if (hasTextDeco) {
+ endTextObject();
+ float descender = tf.getDescender(fontsize) / 1000f;
+ float capHeight = tf.getCapHeight(fontsize) / 1000f;
+ float halfLineWidth = (descender / -8f) / 2f;
+ float endx = (startx + inline.getIPD()) / 1000f;
+ if (inline.hasUnderline()) {
+ ColorType ct = (ColorType) inline.getTrait(Trait.UNDERLINE_COLOR);
+ float y = baseline - descender / 2f;
+ drawBorderLine(startx / 1000f, (y - halfLineWidth) / 1000f,
+ endx, (y + halfLineWidth) / 1000f,
+ true, true, Constants.EN_SOLID, ct);
+ }
+ if (inline.hasOverline()) {
+ ColorType ct = (ColorType) inline.getTrait(Trait.OVERLINE_COLOR);
+ float y = (float)(baseline - (1.1 * capHeight));
+ drawBorderLine(startx / 1000f, (y - halfLineWidth) / 1000f,
+ endx, (y + halfLineWidth) / 1000f,
+ true, true, Constants.EN_SOLID, ct);
+ }
+ if (inline.hasLineThrough()) {
+ ColorType ct = (ColorType) inline.getTrait(Trait.LINETHROUGH_COLOR);
+ float y = (float)(baseline - (0.45 * capHeight));
+ drawBorderLine(startx / 1000f, (y - halfLineWidth) / 1000f,
+ endx, (y + halfLineWidth) / 1000f,
+ true, true, Constants.EN_SOLID, ct);
+ }
+ }
+ }
+
/** Clip using the current path. */
protected abstract void clip();
diff --git a/src/java/org/apache/fop/render/pdf/PDFRenderer.java b/src/java/org/apache/fop/render/pdf/PDFRenderer.java
index 22e32d7dd..cfb73530f 100644
--- a/src/java/org/apache/fop/render/pdf/PDFRenderer.java
+++ b/src/java/org/apache/fop/render/pdf/PDFRenderer.java
@@ -687,6 +687,7 @@ public class PDFRenderer extends AbstractPathOrientedRenderer {
}
}
+ /** @see org.apache.fop.render.AbstractPathOrientedRenderer#updateLineStyle(int) */
private void updateLineStyle(int style) {
switch (style) {
case Constants.EN_DASHED:
@@ -1037,8 +1038,8 @@ public class PDFRenderer extends AbstractPathOrientedRenderer {
int size = ((Integer) ch.getTrait(Trait.FONT_SIZE)).intValue();
// This assumes that *all* CIDFonts use a /ToUnicode mapping
- Typeface f = (Typeface) fontInfo.getFonts().get(name);
- boolean useMultiByte = f.isMultiByte();
+ Typeface tf = (Typeface) fontInfo.getFonts().get(name);
+ boolean useMultiByte = tf.isMultiByte();
// String startText = useMultiByte ? "<FEFF" : "(";
String startText = useMultiByte ? "<" : "(";
@@ -1095,7 +1096,7 @@ public class PDFRenderer extends AbstractPathOrientedRenderer {
currentStream.add(pdf.toString());
- renderTextDecoration(fs, ch, bl, rx);
+ renderTextDecoration(tf, size, ch, bl, rx);
super.renderCharacter(ch);
}
@@ -1111,8 +1112,8 @@ public class PDFRenderer extends AbstractPathOrientedRenderer {
int size = ((Integer) text.getTrait(Trait.FONT_SIZE)).intValue();
// This assumes that *all* CIDFonts use a /ToUnicode mapping
- Typeface f = (Typeface) fontInfo.getFonts().get(name);
- boolean useMultiByte = f.isMultiByte();
+ Typeface tf = (Typeface) fontInfo.getFonts().get(name);
+ boolean useMultiByte = tf.isMultiByte();
// String startText = useMultiByte ? "<FEFF" : "(";
String startText = useMultiByte ? "<" : "(";
@@ -1166,50 +1167,12 @@ public class PDFRenderer extends AbstractPathOrientedRenderer {
currentStream.add(pdf.toString());
- renderTextDecoration(fs, text, bl, rx);
+ renderTextDecoration(tf, size, text, bl, rx);
super.renderText(text);
}
/**
- * Paints the text decoration marks.
- * @param fs Current font
- * @param inline inline area to paint the marks for
- * @param baseline position of the baseline
- * @param startx start IPD
- */
- protected void renderTextDecoration(Font fs, InlineArea inline,
- int baseline, int startx) {
- boolean hasTextDeco = inline.hasUnderline()
- || inline.hasOverline()
- || inline.hasLineThrough();
- if (hasTextDeco) {
- endTextObject();
- updateLineStyle(Constants.EN_SOLID);
- updateLineWidth(fs.getDescender() / -8 / 1000f);
- float endx = (startx + inline.getIPD()) / 1000f;
- if (inline.hasUnderline()) {
- ColorType ct = (ColorType) inline.getTrait(Trait.UNDERLINE_COLOR);
- updateColor(ct, false, null);
- float y = baseline - fs.getDescender() / 2;
- drawLine(startx / 1000f, y / 1000f, endx, y / 1000f);
- }
- if (inline.hasOverline()) {
- ColorType ct = (ColorType) inline.getTrait(Trait.OVERLINE_COLOR);
- updateColor(ct, false, null);
- float y = (float)(baseline - (1.1 * fs.getCapHeight()));
- drawLine(startx / 1000f, y / 1000f, endx, y / 1000f);
- }
- if (inline.hasLineThrough()) {
- ColorType ct = (ColorType) inline.getTrait(Trait.LINETHROUGH_COLOR);
- updateColor(ct, false, null);
- float y = (float)(baseline - (0.45 * fs.getCapHeight()));
- drawLine(startx / 1000f, y / 1000f, endx, y / 1000f);
- }
- }
- }
-
- /**
* Escapes text according to PDF rules.
* @param s Text to escape
* @param fs Font state
diff --git a/src/java/org/apache/fop/render/ps/PSGenerator.java b/src/java/org/apache/fop/render/ps/PSGenerator.java
index f6835c31c..efd07cab0 100644
--- a/src/java/org/apache/fop/render/ps/PSGenerator.java
+++ b/src/java/org/apache/fop/render/ps/PSGenerator.java
@@ -46,6 +46,9 @@ public class PSGenerator {
public static final AtendIndicator ATEND = new AtendIndicator() {
};
+ /** Line feed used by PostScript */
+ public static final char LF = '\n';
+
private OutputStream out;
private boolean commentsEnabled = true;
@@ -87,7 +90,7 @@ public class PSGenerator {
* @throws IOException In case of an I/O problem
*/
public final void newLine() throws IOException {
- out.write('\n');
+ out.write(LF);
}
/**
diff --git a/src/java/org/apache/fop/render/ps/PSRenderer.java b/src/java/org/apache/fop/render/ps/PSRenderer.java
index 5b4688d90..9e9733d68 100644
--- a/src/java/org/apache/fop/render/ps/PSRenderer.java
+++ b/src/java/org/apache/fop/render/ps/PSRenderer.java
@@ -51,6 +51,7 @@ import org.apache.fop.image.ImageFactory;
import org.apache.fop.image.XMLImage;
import org.apache.fop.render.AbstractPathOrientedRenderer;
import org.apache.fop.render.RendererContext;
+import org.apache.fop.util.CharUtilities;
import org.w3c.dom.Document;
@@ -292,7 +293,6 @@ public class PSRenderer extends AbstractPathOrientedRenderer {
/** Restores the last graphics state of the rendering engine. */
public void restoreGraphicsState() {
- endTextObject();
try {
//delegate
gen.restoreGraphicsState();
@@ -301,22 +301,6 @@ public class PSRenderer extends AbstractPathOrientedRenderer {
}
}
- /** Indicates the beginning of a text object. */
- protected void beginTextObject() {
- if (!inTextMode) {
- writeln("BT");
- inTextMode = true;
- }
- }
-
- /** Indicates the end of a text object. */
- protected void endTextObject() {
- if (inTextMode) {
- writeln("ET");
- inTextMode = false;
- }
- }
-
/**
* Concats the transformation matrix.
* @param a A part
@@ -365,6 +349,26 @@ public class PSRenderer extends AbstractPathOrientedRenderer {
gen.useRGBColor(toColor(col));
}
+ /** @see org.apache.fop.render.AbstractPathOrientedRenderer#updateLineStyle(int) */
+ protected void updateLineStyle(int style) {
+ try {
+ switch (style) {
+ case Constants.EN_DASHED:
+ gen.useDash("[3] 0");
+ break;
+ case Constants.EN_DOTTED:
+ gen.useDash("[1 7] 0");
+ break;
+ default:
+ // solid
+ gen.useDash("[] 0");
+ break;
+ }
+ } catch (IOException ioe) {
+ handleIOTrouble(ioe);
+ }
+ }
+
/** @see org.apache.fop.render.AbstractPathOrientedRenderer */
protected void drawBackAndBorders(Area area, float startx, float starty,
float width, float height) {
@@ -668,31 +672,22 @@ public class PSRenderer extends AbstractPathOrientedRenderer {
}
}
- /**
- * Paints text.
- * @param rx X coordinate
- * @param bl Y coordinate
- * @param text Text to paint
- * @param font Font to use
- */
- protected void paintText(int rx, int bl, String text, Typeface font) {
- saveGraphicsState();
- beginTextObject();
- writeln("1 0 0 -1 " + gen.formatDouble(rx / 1000f)
- + " " + gen.formatDouble(bl / 1000f) + " Tm");
+ /** Indicates the beginning of a text object. */
+ protected void beginTextObject() {
+ if (!inTextMode) {
+ saveGraphicsState();
+ writeln("BT");
+ inTextMode = true;
+ }
+ }
- int initialSize = text.length();
- initialSize += initialSize / 2;
- StringBuffer sb = new StringBuffer(initialSize);
- sb.append("(");
- for (int i = 0; i < text.length(); i++) {
- final char c = text.charAt(i);
- final char mapped = font.mapChar(c);
- PSGenerator.escapeChar(mapped, sb);
+ /** Indicates the end of a text object. */
+ protected void endTextObject() {
+ if (inTextMode) {
+ writeln("ET");
+ restoreGraphicsState();
+ inTextMode = false;
}
- sb.append(") t");
- writeln(sb.toString());
- restoreGraphicsState();
}
/**
@@ -703,7 +698,7 @@ public class PSRenderer extends AbstractPathOrientedRenderer {
int fontsize = area.getTraitAsInteger(Trait.FONT_SIZE);
// This assumes that *all* CIDFonts use a /ToUnicode mapping
- Typeface f = (Typeface) fontInfo.getFonts().get(fontname);
+ Typeface tf = (Typeface) fontInfo.getFonts().get(fontname);
//Determine position
int rx = currentIPPosition;
@@ -718,39 +713,56 @@ public class PSRenderer extends AbstractPathOrientedRenderer {
handleIOTrouble(ioe);
}
}
- paintText(rx, bl, area.getTextArea(), f);
+ //paintText(rx, bl, , f);
+ String text = area.getTextArea();
+ beginTextObject();
+ writeln("1 0 0 -1 " + gen.formatDouble(rx / 1000f)
+ + " " + gen.formatDouble(bl / 1000f) + " Tm");
-/*
- String psString = null;
- if (area.getFontState().getLetterSpacing() > 0) {
- //float f = area.getFontState().getLetterSpacing()
- // * 1000 / this.currentFontSize;
- float f = area.getFontState().getLetterSpacing();
- psString = (new StringBuffer().append(f).append(" 0.0 (")
- .append(sb.toString()).append(") A")).toString();
+ int initialSize = text.length();
+ initialSize += initialSize / 2;
+ StringBuffer sb = new StringBuffer(initialSize);
+ int textLen = text.length();
+ if (area.getTextLetterSpaceAdjust() == 0 && area.getTextWordSpaceAdjust() == 0) {
+ sb.append("(");
+ for (int i = 0; i < textLen; i++) {
+ final char c = text.charAt(i);
+ final char mapped = tf.mapChar(c);
+ PSGenerator.escapeChar(mapped, sb);
+ }
+ sb.append(") t");
} else {
- psString = (new StringBuffer("(").append(sb.toString())
- .append(") t")).toString();
+ sb.append("(");
+ int[] offsets = new int[textLen];
+ for (int i = 0; i < textLen; i++) {
+ final char c = text.charAt(i);
+ final char mapped = tf.mapChar(c);
+ int wordSpace;
+ //TODO Synchronize word space behaviour with TextLayoutManager
+ //Check the other renderers, too!
+ if (CharUtilities.isAnySpace(mapped)
+ && mapped != CharUtilities.ZERO_WIDTH_SPACE
+ && mapped != CharUtilities.ZERO_WIDTH_NOBREAK_SPACE) {
+ wordSpace = area.getTextWordSpaceAdjust();
+ } else {
+ wordSpace = 0;
+ }
+ int cw = tf.getWidth(mapped, fontsize) / 1000;
+ offsets[i] = cw + area.getTextLetterSpaceAdjust() + wordSpace;
+ PSGenerator.escapeChar(mapped, sb);
+ }
+ sb.append(")" + PSGenerator.LF + "[");
+ for (int i = 0; i < textLen; i++) {
+ if (i > 0) {
+ sb.append(" ");
+ }
+ sb.append(gen.formatDouble(offsets[i] / 1000f));
+ }
+ sb.append("]" + PSGenerator.LF + "xshow");
}
+ writeln(sb.toString());
-
- // System.out.println("["+s+"] --> ["+sb.toString()+"]");
-
- // comment("% --- InlineArea font-weight="+fontWeight+": " + sb.toString());
- useFont(fs.getFontName(), fs.getFontSize());
- useColor(area.getRed(), area.getGreen(), area.getBlue());
- if (area.getUnderlined() || area.getLineThrough()
- || area.getOverlined())
- write("ULS");
- write(psString);
- if (area.getUnderlined())
- write("ULE");
- if (area.getLineThrough())
- write("SOE");
- if (area.getOverlined())
- write("OLE");
- this.currentXPosition += area.getContentWidth();
- */
+ renderTextDecoration(tf, fontsize, area, bl, rx);
super.renderText(area); //Updates IPD
}