diff --git a/openhtmltopdf-core/src/main/java/com/openhtmltopdf/extend/SVGDrawer.java b/openhtmltopdf-core/src/main/java/com/openhtmltopdf/extend/SVGDrawer.java
index 280aed900..72b7a210f 100644
--- a/openhtmltopdf-core/src/main/java/com/openhtmltopdf/extend/SVGDrawer.java
+++ b/openhtmltopdf-core/src/main/java/com/openhtmltopdf/extend/SVGDrawer.java
@@ -1,9 +1,15 @@
package com.openhtmltopdf.extend;
+import java.util.List;
+
import org.w3c.dom.Element;
+import com.openhtmltopdf.css.sheet.FontFaceRule;
+import com.openhtmltopdf.layout.SharedContext;
import com.openhtmltopdf.render.RenderingContext;
public interface SVGDrawer {
- public void drawSVG(Element svgElement, OutputDevice outputDevice, RenderingContext ctx, double x, double y);
+ public void drawSVG(Element svgElement, OutputDevice outputDevice, RenderingContext ctx, double x, double y, SharedContext shared);
+
+ public void importFontFaceRules(List fontFaces);
}
diff --git a/openhtmltopdf-pdfbox/src/main/java/com/openhtmltopdf/pdfboxout/PdfBoxOutputDevice.java b/openhtmltopdf-pdfbox/src/main/java/com/openhtmltopdf/pdfboxout/PdfBoxOutputDevice.java
index 96c8329ae..e6afdfa77 100644
--- a/openhtmltopdf-pdfbox/src/main/java/com/openhtmltopdf/pdfboxout/PdfBoxOutputDevice.java
+++ b/openhtmltopdf-pdfbox/src/main/java/com/openhtmltopdf/pdfboxout/PdfBoxOutputDevice.java
@@ -53,6 +53,8 @@
import org.apache.pdfbox.pdmodel.PDPage;
import org.apache.pdfbox.pdmodel.PDPageContentStream;
import org.apache.pdfbox.pdmodel.font.PDFont;
+import org.apache.pdfbox.pdmodel.font.PDFontFactory;
+import org.apache.pdfbox.pdmodel.font.PDType1Font;
import org.apache.pdfbox.pdmodel.graphics.image.JPEGFactory;
import org.apache.pdfbox.pdmodel.graphics.image.LosslessFactory;
import org.apache.pdfbox.pdmodel.graphics.image.PDImageXObject;
@@ -1260,8 +1262,6 @@ public void setBidiReorderer(BidiReorderer reorderer) {
@Override
public void drawText(RenderingContext c, String text, float x, float y) {
- // TODO Auto-generated method stub
-
}
@Override
diff --git a/openhtmltopdf-pdfbox/src/main/java/com/openhtmltopdf/pdfboxout/PdfBoxRenderer.java b/openhtmltopdf-pdfbox/src/main/java/com/openhtmltopdf/pdfboxout/PdfBoxRenderer.java
index d3afeb43a..a764ca3bb 100644
--- a/openhtmltopdf-pdfbox/src/main/java/com/openhtmltopdf/pdfboxout/PdfBoxRenderer.java
+++ b/openhtmltopdf-pdfbox/src/main/java/com/openhtmltopdf/pdfboxout/PdfBoxRenderer.java
@@ -102,6 +102,7 @@ public class PdfBoxRenderer {
private PDFCreationListener _listener;
private OutputStream _os;
+ private SVGDrawer _svgImpl;
public PdfBoxRenderer(boolean testMode) {
this(DEFAULT_DOTS_PER_POINT, DEFAULT_DOTS_PER_PIXEL, true, testMode, null, null, null, null);
@@ -109,7 +110,7 @@ public PdfBoxRenderer(boolean testMode) {
public PdfBoxRenderer(float dotsPerPoint, int dotsPerPixel, boolean useSubsets, boolean testMode, HttpStreamFactory factory, FSUriResolver _resolver, FSCache _cache, SVGDrawer svgImpl) {
_pdfDoc = new PDDocument();
-
+ _svgImpl = svgImpl;
_dotsPerPoint = dotsPerPoint;
_testMode = testMode;
_outputDevice = new PdfBoxOutputDevice(dotsPerPoint, testMode);
@@ -255,6 +256,10 @@ public void setDocument(Document doc, String url, NamespaceHandler nsh) {
_sharedContext.setNamespaceHandler(nsh);
_sharedContext.getCss().setDocumentContext(_sharedContext, _sharedContext.getNamespaceHandler(), doc, new NullUserInterface());
getFontResolver().importFontFaces(_sharedContext.getCss().getFontFaceRules());
+
+ if (_svgImpl != null) {
+ _svgImpl.importFontFaceRules(_sharedContext.getCss().getFontFaceRules());
+ }
}
public PDEncryption getPDFEncryption() {
diff --git a/openhtmltopdf-pdfbox/src/main/java/com/openhtmltopdf/pdfboxout/PdfBoxSVGReplacedElement.java b/openhtmltopdf-pdfbox/src/main/java/com/openhtmltopdf/pdfboxout/PdfBoxSVGReplacedElement.java
index 56967b4ad..95c84a9d5 100644
--- a/openhtmltopdf-pdfbox/src/main/java/com/openhtmltopdf/pdfboxout/PdfBoxSVGReplacedElement.java
+++ b/openhtmltopdf-pdfbox/src/main/java/com/openhtmltopdf/pdfboxout/PdfBoxSVGReplacedElement.java
@@ -68,7 +68,7 @@ public int getBaseline() {
@Override
public void paint(RenderingContext c, PdfBoxOutputDevice outputDevice, BlockBox box) {
- svg.drawSVG(e, outputDevice, null, point.getX(), point.getY());
+ svg.drawSVG(e, outputDevice, c, point.getX(), point.getY(), ((PdfBoxOutputDevice) outputDevice).getSharedContext());
}
}
diff --git a/openhtmltopdf-svg-support/src/main/java/com/openhtmltopdf/svgsupport/BatikSVGDrawer.java b/openhtmltopdf-svg-support/src/main/java/com/openhtmltopdf/svgsupport/BatikSVGDrawer.java
index fae511e0b..762298a96 100644
--- a/openhtmltopdf-svg-support/src/main/java/com/openhtmltopdf/svgsupport/BatikSVGDrawer.java
+++ b/openhtmltopdf-svg-support/src/main/java/com/openhtmltopdf/svgsupport/BatikSVGDrawer.java
@@ -1,5 +1,7 @@
package com.openhtmltopdf.svgsupport;
+import java.util.List;
+
import org.apache.batik.anim.dom.SVGDOMImplementation;
import org.apache.batik.transcoder.TranscoderException;
import org.apache.batik.transcoder.TranscoderInput;
@@ -8,8 +10,10 @@
import org.w3c.dom.Element;
import org.w3c.dom.Node;
+import com.openhtmltopdf.css.sheet.FontFaceRule;
import com.openhtmltopdf.extend.OutputDevice;
import com.openhtmltopdf.extend.SVGDrawer;
+import com.openhtmltopdf.layout.SharedContext;
import com.openhtmltopdf.render.RenderingContext;
import com.openhtmltopdf.util.XRLog;
@@ -17,11 +21,18 @@ public class BatikSVGDrawer implements SVGDrawer {
private static final String DEFAULT_VP_WIDTH = "400";
private static final String DEFAULT_VP_HEIGHT = "400";
+ private List rules;
@Override
- public void drawSVG(Element svgElement, OutputDevice outputDevice, RenderingContext ctx, double x, double y) {
- PDFTranscoder transcoder = new PDFTranscoder(outputDevice, ctx, x, y);
-
+ public void importFontFaceRules(List fontFaces) {
+ this.rules = fontFaces;
+ }
+
+ @Override
+ public void drawSVG(Element svgElement, OutputDevice outputDevice, RenderingContext ctx, double x, double y, SharedContext shared) {
+ PDFTranscoder transcoder = new PDFTranscoder(outputDevice, ctx, x, y, shared);
+ transcoder.fontResolver.importFontFaces(rules);
+
try {
DOMImplementation impl = SVGDOMImplementation.getDOMImplementation();
Document newDocument = impl.createDocument(SVGDOMImplementation.SVG_NAMESPACE_URI, "svg", null);
diff --git a/openhtmltopdf-svg-support/src/main/java/com/openhtmltopdf/svgsupport/OpenHtmlGvtFont.java b/openhtmltopdf-svg-support/src/main/java/com/openhtmltopdf/svgsupport/OpenHtmlGvtFont.java
new file mode 100644
index 000000000..f7b205b11
--- /dev/null
+++ b/openhtmltopdf-svg-support/src/main/java/com/openhtmltopdf/svgsupport/OpenHtmlGvtFont.java
@@ -0,0 +1,174 @@
+package com.openhtmltopdf.svgsupport;
+
+import java.awt.Font;
+import java.awt.FontFormatException;
+import java.awt.font.FontRenderContext;
+import java.awt.font.TextAttribute;
+import java.io.ByteArrayInputStream;
+import java.io.IOException;
+import java.text.CharacterIterator;
+
+import org.apache.batik.gvt.font.GVTFont;
+import org.apache.batik.gvt.font.GVTFontFamily;
+import org.apache.batik.gvt.font.GVTGlyphVector;
+import org.apache.batik.gvt.font.GVTLineMetrics;
+
+/**
+ * An adapter around awt.Font to GVTFont.
+ * Code from: http://svn.apache.org/viewvc/xmlgraphics/fop/trunk/fop-core/src/main/java/org/apache/fop/svg/font/FOPGVTFont.java
+ *
+ */
+public class OpenHtmlGvtFont implements GVTFont {
+
+ private final Font baseFont;
+ private final GVTFontFamily fontFamily;
+ private final float size;
+
+ private static int toFontWeight(Float weight) {
+ if (weight == null) {
+ return Font.PLAIN;
+ }
+ else if (weight <= TextAttribute.WEIGHT_BOLD) {
+ return Font.PLAIN;
+ }
+ else {
+ return Font.BOLD;
+ }
+ }
+
+ private static int toStyle(Float posture) {
+ return ((posture != null) && (posture.floatValue() > 0.0))
+ ? Font.ITALIC
+ : Font.PLAIN;
+ }
+
+
+ public OpenHtmlGvtFont(byte[] fontBytes, GVTFontFamily family, float size, Float fontWeight, Float fontStyle) throws FontFormatException {
+ Font font;
+
+ try {
+ font = Font.createFont(Font.TRUETYPE_FONT, new ByteArrayInputStream(fontBytes)).deriveFont(toFontWeight(fontWeight) | toStyle(fontStyle) , size);
+ } catch (IOException e) {
+ // Shouldn't happen
+ e.printStackTrace();
+ font = null;
+ }
+
+ this.baseFont = font;
+ this.fontFamily = family;
+ this.size = size;
+ }
+
+ private OpenHtmlGvtFont(Font font, GVTFontFamily family, float size) {
+ this.baseFont = font;
+ this.fontFamily = family;
+ this.size = size;
+ }
+
+ @Override
+ public boolean canDisplay(char c) {
+ return this.baseFont.canDisplay(c);
+ }
+
+ @Override
+ public int canDisplayUpTo(String str) {
+ for (int i = 0; i < str.length(); i++) {
+ if (!this.baseFont.canDisplay(str.charAt(i)))
+ return i;
+ }
+
+ return -1;
+ }
+
+ @Override
+ public int canDisplayUpTo(char[] str, int start, int limit) {
+ for (int i = start; i < limit; i++) {
+ if (!this.baseFont.canDisplay(str[i]))
+ return i;
+ }
+
+ return -1;
+ }
+
+ @Override
+ public int canDisplayUpTo(CharacterIterator iter, int start, int limit) {
+ for (char c = iter.setIndex(start); iter.getIndex() < limit; c = iter.next()) {
+ if (!canDisplay(c)) {
+ return iter.getIndex();
+ }
+ }
+
+ return -1;
+ }
+
+ @Override
+ public GVTGlyphVector createGlyphVector(FontRenderContext frc, char[] arg1) {
+ return createGlyphVector(frc, new String(arg1));
+ }
+
+ @Override
+ public GVTGlyphVector createGlyphVector(FontRenderContext frc,
+ CharacterIterator arg1) {
+ return new OpenHtmlGvtGlyphVector(this.baseFont.createGlyphVector(frc, arg1), this, frc);
+ }
+
+ @Override
+ public GVTGlyphVector createGlyphVector(FontRenderContext frc, String arg1) {
+ return new OpenHtmlGvtGlyphVector(this.baseFont.createGlyphVector(frc, arg1), this, frc);
+ }
+
+ @Override
+ public GVTGlyphVector createGlyphVector(FontRenderContext frc, int[] arg1,
+ CharacterIterator arg2) {
+ throw new UnsupportedOperationException();
+ }
+
+ @Override
+ public GVTFont deriveFont(float arg0) {
+ Font newFont = this.baseFont.deriveFont(arg0);
+ return new OpenHtmlGvtFont(newFont, this.fontFamily, arg0);
+ }
+
+ @Override
+ public String getFamilyName() {
+ return this.fontFamily.getFamilyName();
+ }
+
+ @Override
+ public float getHKern(int arg0, int arg1) {
+ return 0;
+ }
+
+ @Override
+ public GVTLineMetrics getLineMetrics(String arg0, FontRenderContext arg1) {
+ return new GVTLineMetrics(this.baseFont.getLineMetrics(arg0, arg1));
+ }
+
+ @Override
+ public GVTLineMetrics getLineMetrics(char[] arg0, int arg1, int arg2,
+ FontRenderContext arg3) {
+ return new GVTLineMetrics(this.baseFont.getLineMetrics(arg0, arg1, arg2, arg3));
+ }
+
+ @Override
+ public GVTLineMetrics getLineMetrics(CharacterIterator arg0, int arg1,
+ int arg2, FontRenderContext arg3) {
+ return new GVTLineMetrics(this.baseFont.getLineMetrics(arg0, arg1, arg2, arg3));
+ }
+
+ @Override
+ public GVTLineMetrics getLineMetrics(String arg0, int arg1, int arg2,
+ FontRenderContext arg3) {
+ return new GVTLineMetrics(this.baseFont.getLineMetrics(arg0, arg1, arg2, arg3));
+ }
+
+ @Override
+ public float getSize() {
+ return this.baseFont.getSize() / 1000f;
+ }
+
+ @Override
+ public float getVKern(int arg0, int arg1) {
+ return 0;
+ }
+}
diff --git a/openhtmltopdf-svg-support/src/main/java/com/openhtmltopdf/svgsupport/OpenHtmlGvtFontFamily.java b/openhtmltopdf-svg-support/src/main/java/com/openhtmltopdf/svgsupport/OpenHtmlGvtFontFamily.java
new file mode 100644
index 000000000..e101c7ecb
--- /dev/null
+++ b/openhtmltopdf-svg-support/src/main/java/com/openhtmltopdf/svgsupport/OpenHtmlGvtFontFamily.java
@@ -0,0 +1,106 @@
+package com.openhtmltopdf.svgsupport;
+
+import java.awt.FontFormatException;
+import java.awt.font.TextAttribute;
+import java.io.ByteArrayOutputStream;
+import java.io.FileInputStream;
+import java.io.IOException;
+import java.io.InputStream;
+import java.text.AttributedCharacterIterator;
+import java.util.HashMap;
+import java.util.Map;
+
+import org.apache.batik.gvt.font.GVTFont;
+import org.apache.batik.gvt.font.GVTFontFace;
+import org.apache.batik.gvt.font.GVTFontFamily;
+
+import com.openhtmltopdf.util.XRLog;
+
+public class OpenHtmlGvtFontFamily implements GVTFontFamily {
+
+ private static class FontDescriptor {
+ Float size;
+ Float style;
+ Float weight;
+
+ private boolean eq(Object obj1, Object obj2)
+ {
+ if (obj1 == null && obj2 == null)
+ return true;
+ else if (obj1 == null)
+ return false;
+ else
+ return obj1.equals(obj2);
+
+ }
+
+ @Override
+ public boolean equals(Object obj) {
+ return (obj instanceof FontDescriptor &&
+ eq(((FontDescriptor) obj).style, this.style) &&
+ eq(((FontDescriptor) obj).weight, this.weight) &&
+ eq(((FontDescriptor) obj).size, this.size));
+ }
+
+ @Override
+ public int hashCode() {
+ return (size == null ? 0 : size.hashCode()) + (style == null ? 0 : style.hashCode()) + (weight == null ? 0 : weight.hashCode());
+
+ }
+ }
+
+ private final Map fonts = new HashMap(1);
+ private final String fontFamily;
+
+ public OpenHtmlGvtFontFamily(String family) {
+ this.fontFamily = family;
+ }
+
+ public void addFont(byte[] bytes, float size, Float fontWeight, Float fontStyle) throws FontFormatException {
+ FontDescriptor des = new FontDescriptor();
+ des.size = size;
+ des.style = fontStyle;
+ des.weight = fontWeight;
+
+ fonts.put(des, new OpenHtmlGvtFont(bytes, this, size, fontWeight, fontStyle));
+ }
+
+ @Override
+ public GVTFont deriveFont(float sz, AttributedCharacterIterator arg1) {
+ return deriveFont(sz, arg1.getAttributes());
+ }
+
+ @Override
+ public GVTFont deriveFont(float size, @SuppressWarnings("rawtypes") Map attrs) {
+ Float fontWeight = (Float) attrs.get(TextAttribute.WEIGHT);
+ Float fontStyle = (Float) attrs.get(TextAttribute.POSTURE);
+ Float sz = size;
+
+ FontDescriptor des = new FontDescriptor();
+ des.weight = fontWeight;
+ des.style = fontStyle;
+ des.size = sz;
+
+ if (fonts.containsKey(des)) {
+ return fonts.get(des);
+ }
+
+ return fonts.values().iterator().next().deriveFont(sz);
+ }
+
+ @Override
+ public String getFamilyName() {
+ return this.fontFamily;
+ }
+
+ @Override
+ public GVTFontFace getFontFace() {
+ return new GVTFontFace(this.fontFamily);
+ }
+
+ @Override
+ public boolean isComplex() {
+ return false;
+ }
+
+}
diff --git a/openhtmltopdf-svg-support/src/main/java/com/openhtmltopdf/svgsupport/OpenHtmlGvtGlyphVector.java b/openhtmltopdf-svg-support/src/main/java/com/openhtmltopdf/svgsupport/OpenHtmlGvtGlyphVector.java
new file mode 100644
index 000000000..e157d6db3
--- /dev/null
+++ b/openhtmltopdf-svg-support/src/main/java/com/openhtmltopdf/svgsupport/OpenHtmlGvtGlyphVector.java
@@ -0,0 +1,169 @@
+package com.openhtmltopdf.svgsupport;
+
+import java.awt.Graphics2D;
+import java.awt.Shape;
+import java.awt.font.FontRenderContext;
+import java.awt.font.GlyphJustificationInfo;
+import java.awt.geom.AffineTransform;
+import java.awt.geom.Point2D;
+import java.awt.geom.Rectangle2D;
+import java.text.AttributedCharacterIterator;
+
+import org.apache.batik.gvt.font.GVTFont;
+import org.apache.batik.gvt.font.GVTGlyphMetrics;
+import org.apache.batik.gvt.font.GVTGlyphVector;
+
+public class OpenHtmlGvtGlyphVector implements GVTGlyphVector {
+
+ private final java.awt.font.GlyphVector vec;
+ private final GVTFont font;
+ private final FontRenderContext frc;
+
+ public OpenHtmlGvtGlyphVector(java.awt.font.GlyphVector vec, GVTFont font, FontRenderContext frc) {
+ this.vec = vec;
+ this.font = font;
+ this.frc = frc;
+ }
+
+ @Override
+ public void draw(Graphics2D g2d, AttributedCharacterIterator arg1) {
+ g2d.fill(this.vec.getOutline());
+ }
+
+ @Override
+ public Rectangle2D getBounds2D(AttributedCharacterIterator arg0) {
+ return this.getOutline().getBounds2D();
+ }
+
+ @Override
+ public int getCharacterCount(int start, int end) {
+ return end - start + 1;
+ }
+
+ @Override
+ public GVTFont getFont() {
+ return this.font;
+ }
+
+ @Override
+ public FontRenderContext getFontRenderContext() {
+ return this.frc;
+ }
+
+ @Override
+ public Rectangle2D getGeometricBounds() {
+ return this.vec.getVisualBounds();
+ }
+
+ @Override
+ public Rectangle2D getGlyphCellBounds(int arg0) {
+ throw new UnsupportedOperationException();
+ }
+
+ @Override
+ public int getGlyphCode(int idx) {
+ return this.vec.getGlyphCode(idx);
+ }
+
+ @Override
+ public int[] getGlyphCodes(int arg0, int arg1, int[] arg2) {
+ return this.vec.getGlyphCodes(arg0, arg1, arg2);
+ }
+
+ @Override
+ public GlyphJustificationInfo getGlyphJustificationInfo(int idx) {
+ return this.vec.getGlyphJustificationInfo(idx);
+ }
+
+ @Override
+ public Shape getGlyphLogicalBounds(int arg0) {
+ return this.vec.getGlyphLogicalBounds(arg0);
+ }
+
+ @Override
+ public GVTGlyphMetrics getGlyphMetrics(int arg0) {
+ return new GVTGlyphMetrics(this.vec.getGlyphMetrics(arg0), 100000);
+ }
+
+ @Override
+ public Shape getGlyphOutline(int arg0) {
+ return this.vec.getGlyphOutline(arg0);
+ }
+
+ @Override
+ public Point2D getGlyphPosition(int arg0) {
+ return this.vec.getGlyphPosition(arg0);
+ }
+
+ @Override
+ public float[] getGlyphPositions(int arg0, int arg1, float[] arg2) {
+ return this.vec.getGlyphPositions(arg0, arg1, arg2);
+ }
+
+ @Override
+ public AffineTransform getGlyphTransform(int arg0) {
+ return this.vec.getGlyphTransform(arg0);
+ }
+
+ @Override
+ public Shape getGlyphVisualBounds(int arg0) {
+ return this.vec.getGlyphVisualBounds(arg0);
+ }
+
+ @Override
+ public Rectangle2D getLogicalBounds() {
+ return this.vec.getLogicalBounds();
+ }
+
+ @Override
+ public int getNumGlyphs() {
+ return this.vec.getNumGlyphs();
+ }
+
+ @Override
+ public Shape getOutline() {
+ return this.vec.getOutline();
+ }
+
+ @Override
+ public Shape getOutline(float arg0, float arg1) {
+ return this.vec.getOutline(arg0, arg1);
+ }
+
+ @Override
+ public boolean isGlyphVisible(int arg0) {
+ return true;
+ }
+
+ @Override
+ public boolean isReversed() {
+ return false;
+ }
+
+ @Override
+ public void maybeReverse(boolean arg0) {
+ }
+
+ @Override
+ public void performDefaultLayout() {
+ this.vec.performDefaultLayout();
+ }
+
+ @Override
+ public void setGlyphPosition(int arg0, Point2D arg1) {
+ if (arg0 == this.getNumGlyphs())
+ return;
+
+ this.vec.setGlyphPosition(arg0, arg1);
+ }
+
+ @Override
+ public void setGlyphTransform(int arg0, AffineTransform arg1) {
+ this.vec.setGlyphTransform(arg0, arg1);
+ }
+
+ @Override
+ public void setGlyphVisible(int arg0, boolean arg1) {
+ }
+
+}
diff --git a/openhtmltopdf-svg-support/src/main/java/com/openhtmltopdf/svgsupport/OpenHtmlUserAgent.java b/openhtmltopdf-svg-support/src/main/java/com/openhtmltopdf/svgsupport/OpenHtmlUserAgent.java
new file mode 100644
index 000000000..38b99d93e
--- /dev/null
+++ b/openhtmltopdf-svg-support/src/main/java/com/openhtmltopdf/svgsupport/OpenHtmlUserAgent.java
@@ -0,0 +1,260 @@
+package com.openhtmltopdf.svgsupport;
+
+import java.awt.Cursor;
+import java.awt.Point;
+import java.awt.geom.AffineTransform;
+import java.awt.geom.Dimension2D;
+
+import org.apache.batik.bridge.BridgeExtension;
+import org.apache.batik.bridge.ExternalResourceSecurity;
+import org.apache.batik.bridge.FontFamilyResolver;
+import org.apache.batik.bridge.Mark;
+import org.apache.batik.bridge.ScriptSecurity;
+import org.apache.batik.bridge.UserAgent;
+import org.apache.batik.gvt.event.EventDispatcher;
+import org.apache.batik.util.ParsedURL;
+import org.w3c.dom.Element;
+import org.w3c.dom.svg.SVGAElement;
+import org.w3c.dom.svg.SVGDocument;
+
+import com.openhtmltopdf.svgsupport.PDFTranscoder.OpenHtmlFontResolver;
+
+public class OpenHtmlUserAgent implements UserAgent {
+
+ private final OpenHtmlFontResolver resolver;
+
+ public OpenHtmlUserAgent(OpenHtmlFontResolver resolver) {
+ this.resolver = resolver;
+ }
+
+ @Override
+ public boolean supportExtension(String arg0) {
+ // TODO Auto-generated method stub
+ return false;
+ }
+
+ @Override
+ public String showPrompt(String arg0, String arg1) {
+ // TODO Auto-generated method stub
+ return null;
+ }
+
+ @Override
+ public String showPrompt(String arg0) {
+ // TODO Auto-generated method stub
+ return null;
+ }
+
+ @Override
+ public boolean showConfirm(String arg0) {
+ // TODO Auto-generated method stub
+ return false;
+ }
+
+ @Override
+ public void showAlert(String arg0) {
+ // TODO Auto-generated method stub
+
+ }
+
+ @Override
+ public void setTransform(AffineTransform arg0) {
+ // TODO Auto-generated method stub
+
+ }
+
+ @Override
+ public void setTextSelection(Mark arg0, Mark arg1) {
+ // TODO Auto-generated method stub
+
+ }
+
+ @Override
+ public void setSVGCursor(Cursor arg0) {
+ // TODO Auto-generated method stub
+
+ }
+
+ @Override
+ public void registerExtension(BridgeExtension arg0) {
+ // TODO Auto-generated method stub
+
+ }
+
+ @Override
+ public void openLink(SVGAElement arg0) {
+ // TODO Auto-generated method stub
+
+ }
+
+ @Override
+ public void loadDocument(String arg0) {
+ System.err.println("LOAD DOC: " + arg0);
+
+ }
+
+ @Override
+ public boolean isXMLParserValidating() {
+ // TODO Auto-generated method stub
+ return false;
+ }
+
+ @Override
+ public boolean hasFeature(String arg0) {
+ // TODO Auto-generated method stub
+ return false;
+ }
+
+ @Override
+ public void handleElement(Element arg0, Object arg1) {
+ // TODO Auto-generated method stub
+
+ }
+
+ @Override
+ public String getXMLParserClassName() {
+ // TODO Auto-generated method stub
+ return null;
+ }
+
+ @Override
+ public Dimension2D getViewportSize() {
+ // TODO Auto-generated method stub
+ return null;
+ }
+
+ @Override
+ public String getUserStyleSheetURI() {
+ // TODO Auto-generated method stub
+ return null;
+ }
+
+ @Override
+ public AffineTransform getTransform() {
+ // TODO Auto-generated method stub
+ return null;
+ }
+
+ @Override
+ public ScriptSecurity getScriptSecurity(String arg0, ParsedURL arg1,
+ ParsedURL arg2) {
+ // TODO Auto-generated method stub
+ return null;
+ }
+
+ @Override
+ public float getPixelUnitToMillimeter() {
+ // TODO Auto-generated method stub
+ return 0;
+ }
+
+ @Override
+ public float getPixelToMM() {
+ // TODO Auto-generated method stub
+ return 0;
+ }
+
+ @Override
+ public float getMediumFontSize() {
+ // TODO Auto-generated method stub
+ return 0;
+ }
+
+ @Override
+ public String getMedia() {
+ return "print";
+ }
+
+ @Override
+ public float getLighterFontWeight(float arg0) {
+ // TODO Auto-generated method stub
+ return 0;
+ }
+
+ @Override
+ public String getLanguages() {
+ // TODO Auto-generated method stub
+ return null;
+ }
+
+ @Override
+ public FontFamilyResolver getFontFamilyResolver() {
+ return this.resolver;
+ }
+
+ @Override
+ public ExternalResourceSecurity getExternalResourceSecurity(ParsedURL arg0,
+ ParsedURL arg1) {
+ // TODO Auto-generated method stub
+ return null;
+ }
+
+ @Override
+ public EventDispatcher getEventDispatcher() {
+ // TODO Auto-generated method stub
+ return null;
+ }
+
+ @Override
+ public String getDefaultFontFamily() {
+ // TODO Auto-generated method stub
+ return null;
+ }
+
+ @Override
+ public Point getClientAreaLocationOnScreen() {
+ // TODO Auto-generated method stub
+ return null;
+ }
+
+ @Override
+ public SVGDocument getBrokenLinkDocument(Element arg0, String arg1,
+ String arg2) {
+ // TODO Auto-generated method stub
+ return null;
+ }
+
+ @Override
+ public float getBolderFontWeight(float arg0) {
+ // TODO Auto-generated method stub
+ return 0;
+ }
+
+ @Override
+ public String getAlternateStyleSheet() {
+ // TODO Auto-generated method stub
+ return null;
+ }
+
+ @Override
+ public void displayMessage(String arg0) {
+ // TODO Auto-generated method stub
+
+ }
+
+ @Override
+ public void displayError(Exception arg0) {
+ // TODO Auto-generated method stub
+
+ }
+
+ @Override
+ public void deselectAll() {
+ // TODO Auto-generated method stub
+
+ }
+
+ @Override
+ public void checkLoadScript(String arg0, ParsedURL arg1, ParsedURL arg2)
+ throws SecurityException {
+ // TODO Auto-generated method stub
+
+ }
+
+ @Override
+ public void checkLoadExternalResource(ParsedURL arg0, ParsedURL arg1)
+ throws SecurityException {
+ // TODO Auto-generated method stub
+
+ }
+}
diff --git a/openhtmltopdf-svg-support/src/main/java/com/openhtmltopdf/svgsupport/PDFGraphics2DOutputDeviceAdapter.java b/openhtmltopdf-svg-support/src/main/java/com/openhtmltopdf/svgsupport/PDFGraphics2DOutputDeviceAdapter.java
index d3aeb635a..a0020020a 100644
--- a/openhtmltopdf-svg-support/src/main/java/com/openhtmltopdf/svgsupport/PDFGraphics2DOutputDeviceAdapter.java
+++ b/openhtmltopdf-svg-support/src/main/java/com/openhtmltopdf/svgsupport/PDFGraphics2DOutputDeviceAdapter.java
@@ -170,13 +170,13 @@ public void drawRenderableImage(RenderableImage img, AffineTransform xform) {
@Override
public void drawString(String str, float x, float y) {
- System.out.println("DRAW STRING");
+ this.od.setColor(new FSRGBColor(128, 128, 128));
+ this.od.drawText(this.ctx, str, x, y);
}
@Override
public void drawString(AttributedCharacterIterator iterator, float x, float y) {
- System.out.println("DRAW STRING");
-
+System.out.println("DRAWING STRING");
}
@Override
diff --git a/openhtmltopdf-svg-support/src/main/java/com/openhtmltopdf/svgsupport/PDFTranscoder.java b/openhtmltopdf-svg-support/src/main/java/com/openhtmltopdf/svgsupport/PDFTranscoder.java
index b85598607..2361edb63 100644
--- a/openhtmltopdf-svg-support/src/main/java/com/openhtmltopdf/svgsupport/PDFTranscoder.java
+++ b/openhtmltopdf-svg-support/src/main/java/com/openhtmltopdf/svgsupport/PDFTranscoder.java
@@ -1,49 +1,187 @@
package com.openhtmltopdf.svgsupport;
-import java.awt.Cursor;
-import java.awt.Point;
-import java.awt.geom.AffineTransform;
+import java.awt.FontFormatException;
+import java.awt.font.TextAttribute;
+import java.io.InputStream;
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
-import org.apache.batik.bridge.BridgeExtension;
+import org.apache.batik.bridge.FontFace;
import org.apache.batik.bridge.FontFamilyResolver;
-import org.apache.batik.bridge.Mark;
-import org.apache.batik.bridge.ScriptSecurity;
-import org.apache.batik.bridge.UserAgent;
+import org.apache.batik.gvt.font.GVTFontFamily;
import org.apache.batik.transcoder.ErrorHandler;
import org.apache.batik.transcoder.SVGAbstractTranscoder;
import org.apache.batik.transcoder.TranscoderException;
import org.apache.batik.transcoder.TranscoderOutput;
-import org.apache.batik.transcoder.TranscodingHints;
-import org.apache.batik.util.ParsedURL;
import org.w3c.dom.Document;
-import org.w3c.dom.Element;
-import org.w3c.dom.svg.SVGAElement;
-import org.w3c.dom.svg.SVGDocument;
+import com.openhtmltopdf.css.constants.CSSName;
+import com.openhtmltopdf.css.constants.IdentValue;
+import com.openhtmltopdf.css.sheet.FontFaceRule;
+import com.openhtmltopdf.css.style.CalculatedStyle;
+import com.openhtmltopdf.css.style.FSDerivedValue;
import com.openhtmltopdf.extend.OutputDevice;
+import com.openhtmltopdf.layout.SharedContext;
import com.openhtmltopdf.render.RenderingContext;
import com.openhtmltopdf.util.XRLog;
public class PDFTranscoder extends SVGAbstractTranscoder {
private final PDFGraphics2DOutputDeviceAdapter od;
+ public final OpenHtmlFontResolver fontResolver;
- public PDFTranscoder(OutputDevice od, RenderingContext ctx, double x, double y) {
+ public PDFTranscoder(OutputDevice od, RenderingContext ctx, double x, double y, SharedContext shared) {
this.od = new PDFGraphics2DOutputDeviceAdapter(ctx, od, x, y);
+ this.fontResolver = new OpenHtmlFontResolver(shared);
}
+ public static class OpenHtmlFontResolver implements FontFamilyResolver {
+ private final Map families = new HashMap(4);
+ private final SharedContext ctx;
+
+ public OpenHtmlFontResolver(SharedContext ctx) {
+ this.ctx = ctx;
+ }
+
+ @Override
+ public GVTFontFamily resolve(String arg0, FontFace arg1) {
+ return null;
+ }
+
+ @Override
+ public GVTFontFamily resolve(String family) {
+ if (families.containsKey(family))
+ return families.get(family);
+
+ return null;
+ }
+
+ @Override
+ public GVTFontFamily loadFont(InputStream arg0, FontFace arg1)
+ throws Exception {
+ return null;
+ }
+
+ @Override
+ public GVTFontFamily getFamilyThatCanDisplay(char arg0) {
+ return null;
+ }
+
+ @Override
+ public GVTFontFamily getDefault() {
+ return null;
+ }
+
+ private Float getStyle(IdentValue fontStyle) {
+
+ if (fontStyle == IdentValue.ITALIC ||
+ fontStyle == IdentValue.OBLIQUE)
+ return TextAttribute.POSTURE_OBLIQUE;
+
+ return null;
+ }
+
+ private Float getWeight(IdentValue weight) {
+ if (weight == IdentValue.NORMAL) {
+ return TextAttribute.WEIGHT_REGULAR;
+ } else if (weight == IdentValue.BOLD) {
+ return TextAttribute.WEIGHT_BOLD;
+ } else if (weight == IdentValue.FONT_WEIGHT_100) {
+ return TextAttribute.WEIGHT_EXTRA_LIGHT;
+ } else if (weight == IdentValue.FONT_WEIGHT_200) {
+ return TextAttribute.WEIGHT_LIGHT;
+ } else if (weight == IdentValue.FONT_WEIGHT_300) {
+ return TextAttribute.WEIGHT_LIGHT;
+ } else if (weight == IdentValue.FONT_WEIGHT_400) {
+ return TextAttribute.WEIGHT_MEDIUM;
+ } else if (weight == IdentValue.FONT_WEIGHT_500) {
+ return TextAttribute.WEIGHT_SEMIBOLD;
+ } else if (weight == IdentValue.FONT_WEIGHT_600) {
+ return TextAttribute.WEIGHT_SEMIBOLD;
+ } else if (weight == IdentValue.FONT_WEIGHT_700) {
+ return TextAttribute.WEIGHT_BOLD;
+ } else if (weight == IdentValue.FONT_WEIGHT_800) {
+ return TextAttribute.WEIGHT_EXTRABOLD;
+ } else if (weight == IdentValue.FONT_WEIGHT_900) {
+ return TextAttribute.WEIGHT_ULTRABOLD;
+ } else if (weight == IdentValue.LIGHTER) {
+ // FIXME
+ return TextAttribute.WEIGHT_MEDIUM;
+ } else if (weight == IdentValue.BOLDER) {
+ // FIXME
+ return TextAttribute.WEIGHT_MEDIUM;
+ }
+ else {
+ return null;
+ }
+ }
+
+ private void addFontFaceFont(
+ String fontFamilyNameOverride, IdentValue fontWeightOverride, IdentValue fontStyleOverride, String uri, byte[] font1)
+ throws FontFormatException {
+
+ OpenHtmlGvtFontFamily family = null;
+
+ if (families.containsKey(fontFamilyNameOverride))
+ family = families.get(fontFamilyNameOverride);
+ else {
+ family = new OpenHtmlGvtFontFamily(fontFamilyNameOverride);
+ families.put(fontFamilyNameOverride, family);
+ }
+
+ family.addFont(font1, 1, getWeight(fontWeightOverride), getStyle(fontStyleOverride));
+ }
+
+
+ public void importFontFaces(List fontFaces) {
+ for (FontFaceRule rule : fontFaces) {
+ CalculatedStyle style = rule.getCalculatedStyle();
+
+ FSDerivedValue src = style.valueByName(CSSName.SRC);
+ if (src == IdentValue.NONE) {
+ continue;
+ }
+
+ byte[] font1 = ctx.getUac().getBinaryResource(src.asString());
+ if (font1 == null) {
+ XRLog.exception("Could not load font " + src.asString());
+ continue;
+ }
+
+ String fontFamily = null;
+ IdentValue fontWeight = null;
+ IdentValue fontStyle = null;
+
+ if (rule.hasFontFamily()) {
+ fontFamily = style.valueByName(CSSName.FONT_FAMILY).asString();
+ }
+
+ if (rule.hasFontWeight()) {
+ fontWeight = style.getIdent(CSSName.FONT_WEIGHT);
+ }
+
+ if (rule.hasFontStyle()) {
+ fontStyle = style.getIdent(CSSName.FONT_STYLE);
+ }
+
+ try {
+ addFontFaceFont(fontFamily, fontWeight, fontStyle, src.asString(), font1);
+ } catch (FontFormatException e) {
+ XRLog.exception("Couldn't read font", e);
+ continue;
+ }
+ }
+ }
+ }
+
@Override
protected void transcode(Document svg, String uri, TranscoderOutput out) throws TranscoderException {
+ this.userAgent = new OpenHtmlUserAgent(this.fontResolver);
super.transcode(svg, uri, out);
this.root.paint(od);
}
- @Override
- public TranscodingHints getTranscodingHints() {
- // TODO Auto-generated method stub
- return super.getTranscodingHints();
- }
-
@Override
public ErrorHandler getErrorHandler() {
return new ErrorHandler() {