From 0f35bc7169d84932ede357e9f625da8b272132a3 Mon Sep 17 00:00:00 2001 From: Keiron Liddle Date: Wed, 15 Aug 2001 10:33:34 +0000 Subject: [PATCH] added support for embedded fonts for svg text, also added proper escaping git-svn-id: https://svn.apache.org/repos/asf/xmlgraphics/fop/trunk@194425 13f79535-47bb-0310-9956-ffa450edef68 --- src/org/apache/fop/svg/PDFGraphics2D.java | 152 ++++++++++++++++++--- src/org/apache/fop/svg/PDFTextPainter.java | 4 + 2 files changed, 138 insertions(+), 18 deletions(-) diff --git a/src/org/apache/fop/svg/PDFGraphics2D.java b/src/org/apache/fop/svg/PDFGraphics2D.java index fa3e713dd..7b117ea3c 100644 --- a/src/org/apache/fop/svg/PDFGraphics2D.java +++ b/src/org/apache/fop/svg/PDFGraphics2D.java @@ -13,6 +13,8 @@ import org.apache.fop.fonts.*; import org.apache.fop.render.pdf.*; import org.apache.fop.image.*; import org.apache.fop.datatypes.ColorSpace; +import org.apache.fop.render.pdf.CIDFont; +import org.apache.fop.render.pdf.fonts.LazyFont; import org.apache.batik.ext.awt.g2d.*; import org.apache.batik.ext.awt.image.GraphicsUtil; @@ -30,6 +32,7 @@ import java.io.*; import java.util.Map; import java.util.Vector; +import java.util.Hashtable; /** * This concrete implementation of AbstractGraphics2D is a @@ -57,6 +60,7 @@ public class PDFGraphics2D extends AbstractGraphics2D { PDFAnnotList currentAnnotList = null; protected FontState fontState; + protected FontState ovFontState = null; /** * the current stream to add PDF commands to @@ -116,6 +120,10 @@ public class PDFGraphics2D extends AbstractGraphics2D { gc = c; } + public void setOverrideFontState(FontState infont) { + ovFontState = infont; + } + /** * This constructor supports the create method */ @@ -787,25 +795,30 @@ public class PDFGraphics2D extends AbstractGraphics2D { currentStream.write("BT\n"); - Font gFont = getFont(); - String name = gFont.getName(); - if (name.equals("sanserif")) { - name = "sans-serif"; - } - int size = gFont.getSize(); - String style = gFont.isItalic() ? "italic" : "normal"; - String weight = gFont.isBold() ? "bold" : "normal"; - try { - fontState = new FontState(fontState.getFontInfo(), name, style, - weight, size * 1000, 0); - } catch (org.apache.fop.apps.FOPException fope) { - fope.printStackTrace(); + if(ovFontState == 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"; + try { + fontState = new FontState(fontState.getFontInfo(), n, style, + weight, siz * 1000, 0); + } catch (org.apache.fop.apps.FOPException fope) { + fope.printStackTrace(); + } + } else { + fontState = ovFontState; + ovFontState = null; } + String name; + int size; name = fontState.getFontName(); size = fontState.getFontSize() / 1000; - // System.out.println("ffn:" + gFont.getFontName() + "fn:" + gFont.getName() + " ff:" + gFont.getFamily() + " fs:" + fontState.getFontName()); - if ((!name.equals(this.currentFontName)) || (size != this.currentFontSize)) { this.currentFontName = name; @@ -813,6 +826,31 @@ public class PDFGraphics2D extends AbstractGraphics2D { currentStream.write("/" + name + " " + size + " Tf\n"); } + + Hashtable kerning = null; + boolean kerningAvailable = false; + + kerning = fontState.getKerning(); + if (kerning != null &&!kerning.isEmpty()) { + kerningAvailable = true; + } + + // This assumes that *all* CIDFonts use a /ToUnicode mapping + boolean useMultiByte = false; + org.apache.fop.render.pdf.Font f = + (org.apache.fop.render.pdf.Font)fontState.getFontInfo().getFonts().get(name); + if (f instanceof LazyFont){ + if(((LazyFont) f).getRealFont() instanceof CIDFont){ + useMultiByte = true; + } + } else if (f instanceof CIDFont){ + useMultiByte = true; + } + + // String startText = useMultiByte ? " " : ") "; + AffineTransform trans = getTransform(); trans.translate(x, y); double[] vals = new double[6]; @@ -823,12 +861,89 @@ public class PDFGraphics2D extends AbstractGraphics2D { + PDFNumber.doubleOut(vals[2]) + " " + PDFNumber.doubleOut(-vals[3]) + " " + PDFNumber.doubleOut(vals[4]) + " " - + PDFNumber.doubleOut(vals[5]) + " Tm (" + s - + ") Tj\n"); + + PDFNumber.doubleOut(vals[5]) + " Tm [" + startText); + + int l = s.length(); + + for (int i = 0; i < l; i++) { + char ch = fontState.mapChar(s.charAt(i)); + + if (!useMultiByte) { + if (ch > 127) { + currentStream.write("\\"); + currentStream.write(Integer.toOctalString((int)ch)); + } else { + switch (ch) { + case '(': + case ')': + case '\\': + currentStream.write("\\"); + break; + } + currentStream.write(ch); + } + } else { + currentStream.write(getUnicodeString(ch)); + } + + if (kerningAvailable && (i + 1) < l) { + addKerning(currentStream, (new Integer((int)ch)), + (new Integer((int)fontState.mapChar(s.charAt(i + 1)))), + kerning, startText, endText); + } + + } + currentStream.write(endText); + + + currentStream.write("] TJ\n"); currentStream.write("ET\n"); } + private void addKerning(StringWriter buf, Integer ch1, Integer ch2, + Hashtable kerning, String startText, + String endText) { + Hashtable kernPair = (Hashtable)kerning.get(ch1); + + if (kernPair != null) { + Integer width = (Integer)kernPair.get(ch2); + if (width != null) { + currentStream.write(endText + (-width.intValue()) + " " + startText); + } + } + } + + /** + * Convert a char to a multibyte hex representation + */ + private String getUnicodeString(char c) { + + StringBuffer buf = new StringBuffer(4); + byte[] uniBytes = null; + try { + char[] a = { + c + }; + uniBytes = new String(a).getBytes("UnicodeBigUnmarked"); + } catch (Exception e) { + // This should never fail + } + + for (int i = 0; i < uniBytes.length; i++) { + int b = (uniBytes[i] < 0) ? (int)(256 + uniBytes[i]) + : (int)uniBytes[i]; + + String hexString = Integer.toHexString(b); + if (hexString.length() == 1) + buf = buf.append("0" + hexString); + else + buf = buf.append(hexString); + } + + return buf.toString(); + } + /** * Renders the text of the specified iterator, using the * Graphics2D context's current Paint. The @@ -856,7 +971,6 @@ public class PDFGraphics2D extends AbstractGraphics2D { float y) { System.err.println("drawString(AttributedCharacterIterator)"); - currentStream.write("BT\n"); Shape imclip = getClip(); writeClip(imclip); Color c = getColor(); @@ -864,6 +978,8 @@ public class PDFGraphics2D extends AbstractGraphics2D { c = getBackground(); applyColor(c, false); + currentStream.write("BT\n"); + AffineTransform trans = getTransform(); trans.translate(x, y); double[] vals = new double[6]; diff --git a/src/org/apache/fop/svg/PDFTextPainter.java b/src/org/apache/fop/svg/PDFTextPainter.java index db9ed1b92..ae5512e34 100644 --- a/src/org/apache/fop/svg/PDFTextPainter.java +++ b/src/org/apache/fop/svg/PDFTextPainter.java @@ -125,6 +125,10 @@ public class PDFTextPainter implements TextPainter { } catch (org.apache.fop.apps.FOPException fope) { fope.printStackTrace(); } + } else { + if(g2d instanceof PDFGraphics2D) { + ((PDFGraphics2D)g2d).setOverrideFontState(fontState); + } } int fStyle = Font.PLAIN; if (fontState.getFontWeight().equals("bold")) { -- 2.39.5