You are viewing a plain text version of this content. The canonical link for it is here.
Posted to batik-dev@xmlgraphics.apache.org by be...@apache.org on 2001/08/03 06:21:54 UTC
cvs commit: xml-batik/sources/org/apache/batik/svggen SVGFont.java SVGFontDescriptor.java SVGGraphicContextConverter.java SVGGraphics2D.java SVGGraphics2DUnitTester.java SVGSyntax.java
bella 01/08/02 21:21:54
Modified: sources/org/apache/batik/svggen SVGFont.java
SVGFontDescriptor.java
SVGGraphicContextConverter.java SVGGraphics2D.java
SVGGraphics2DUnitTester.java SVGSyntax.java
Log:
SVGGraphics2D now generates SVG fonts
Revision Changes Path
1.13 +233 -5 xml-batik/sources/org/apache/batik/svggen/SVGFont.java
Index: SVGFont.java
===================================================================
RCS file: /home/cvs/xml-batik/sources/org/apache/batik/svggen/SVGFont.java,v
retrieving revision 1.12
retrieving revision 1.13
diff -u -r1.12 -r1.13
--- SVGFont.java 2001/04/26 14:17:19 1.12
+++ SVGFont.java 2001/08/03 04:21:53 1.13
@@ -12,6 +12,16 @@
import java.util.HashMap;
import java.util.Map;
import java.awt.font.TextAttribute;
+import java.awt.font.GlyphVector;
+import java.awt.font.GlyphMetrics;
+import java.awt.font.LineMetrics;
+import java.awt.font.FontRenderContext;
+import java.awt.geom.AffineTransform;
+import java.awt.Shape;
+
+import org.w3c.dom.Document;
+import org.w3c.dom.Element;
+import org.w3c.dom.NodeList;
import org.apache.batik.ext.awt.g2d.GraphicContext;
@@ -21,7 +31,7 @@
*
* @author <a href="mailto:cjolif@ilog.fr">Christophe Jolif</a>
* @author <a href="mailto:vincent.hardy@eng.sun.com">Vincent Hardy</a>
- * @version $Id: SVGFont.java,v 1.12 2001/04/26 14:17:19 cjolif Exp $
+ * @version $Id: SVGFont.java,v 1.13 2001/08/03 04:21:53 bella Exp $
*/
public class SVGFont extends AbstractSVGConverter {
public static final float EXTRA_LIGHT =
@@ -120,6 +130,61 @@
}
/**
+ * The common font size to use when generating all SVG fonts.
+ */
+ static final int COMMON_FONT_SIZE = 100;
+
+ /**
+ * Used to keep track of which characters have been rendered by each font
+ * used.
+ */
+ static Map fontStringMap = new HashMap();
+
+ /**
+ * @param generatorContext used to build Elements
+ */
+ public SVGFont(SVGGeneratorContext generatorContext) {
+ super(generatorContext);
+ fontStringMap = new HashMap();
+ }
+
+ /**
+ * Records that the specified font has been used to draw the text string.
+ * This is so we can keep track of which glyphs are required for each
+ * SVG font that is generated.
+ */
+ public static void recordFontUsage(String string, Font font) {
+
+ Font commonSizeFont = createCommonSizeFont(font);
+ String fontKey = commonSizeFont.getFamily() + commonSizeFont.getStyle();
+ String textUsingFont = (String)fontStringMap.get(fontKey);
+ if (textUsingFont == null) {
+ // font has not been used before
+ textUsingFont = "";
+ }
+ // append any new characters to textUsingFont
+ char ch;
+ for (int i = 0; i < string.length(); i++) {
+ ch = string.charAt(i);
+ if (textUsingFont.indexOf(ch) == -1) {
+ textUsingFont += ch;
+ }
+ }
+ fontStringMap.put(fontKey, textUsingFont);
+ }
+
+ /**
+ * Creates a new Font that is of the common font size used for generating
+ * SVG fonts. The new Font will be the same as the specified font, with
+ * only its size attribute modified.
+ */
+ private static Font createCommonSizeFont(Font font) {
+ HashMap attributes = new HashMap(font.getAttributes());
+ attributes.put(TextAttribute.SIZE, new Float(COMMON_FONT_SIZE));
+ return new Font(attributes);
+ }
+
+ /**
* Converts part or all of the input GraphicContext into
* a set of attribute/value pairs and related definitions
*
@@ -130,21 +195,184 @@
* @see org.apache.batik.svggen.SVGDescriptor
*/
public SVGDescriptor toSVG(GraphicContext gc) {
- return toSVG(gc.getFont());
+ return toSVG(gc.getFont(), gc.getFontRenderContext());
}
/**
* @param font Font object which should be converted to a set
* of SVG attributes
+ * @param frc The FontRenderContext which will be used to generate glyph
+ * elements for the SVGFont definition element
* @return description of attribute values that describe the font
*/
- public static SVGFontDescriptor toSVG(Font font) {
+ public SVGFontDescriptor toSVG(Font font, FontRenderContext frc) {
+
String fontSize = "" + font.getSize();
String fontWeight = weightToSVG(font);
String fontStyle = styleToSVG(font);
String fontFamilyStr = familyToSVG(font);
- return new SVGFontDescriptor(fontSize, fontWeight,
- fontStyle, fontFamilyStr);
+
+ Font commonSizeFont = createCommonSizeFont(font);
+ String fontKey = commonSizeFont.getFamily() + commonSizeFont.getStyle();
+
+ String textUsingFont = (String)fontStringMap.get(fontKey);
+
+ if (textUsingFont == null) {
+ // this font hasn't been used by any text yet,
+ // so don't create an SVG Font element for it
+ return new SVGFontDescriptor(fontSize, fontWeight,
+ fontStyle, fontFamilyStr,
+ null);
+ }
+
+ Document domFactory = generatorContext.domFactory;
+
+ // see if a description already exists for this font
+ SVGFontDescriptor fontDesc =
+ (SVGFontDescriptor)descMap.get(fontKey);
+
+ Element fontDef;
+
+ if (fontDesc != null) {
+
+ // use the SVG Font element that has already been created
+ fontDef = fontDesc.getDef();
+
+ } else {
+
+ // create a new SVG Font element
+ fontDef = domFactory.createElementNS(SVG_NAMESPACE_URI,
+ SVG_FONT_TAG);
+
+ //
+ // create the font-face element
+ //
+ Element fontFace = domFactory.createElementNS(SVG_NAMESPACE_URI,
+ SVG_FONT_FACE_TAG);
+ String svgFontFamilyString = fontFamilyStr;
+ if (fontFamilyStr.startsWith("'") && fontFamilyStr.endsWith("'")) {
+ // get rid of the quotes
+ svgFontFamilyString
+ = fontFamilyStr.substring(1, fontFamilyStr.length()-1);
+ }
+ fontFace.setAttributeNS(null, SVG_FONT_FAMILY_ATTRIBUTE,
+ svgFontFamilyString);
+ fontFace.setAttributeNS(null, SVG_FONT_WEIGHT_ATTRIBUTE,
+ fontWeight);
+ fontFace.setAttributeNS(null, SVG_FONT_STYLE_ATTRIBUTE,
+ fontStyle);
+ fontFace.setAttributeNS(null, SVG_UNITS_PER_EM_ATTRIBUTE,
+ ""+COMMON_FONT_SIZE);
+ fontDef.appendChild(fontFace);
+
+ //
+ // create missing glyph element
+ //
+ Element missingGlyphElement
+ = domFactory.createElementNS(SVG_NAMESPACE_URI,
+ SVG_MISSING_GLYPH_TAG);
+
+ int missingGlyphCode[] = new int[1];
+ missingGlyphCode[0] = commonSizeFont.getMissingGlyphCode();
+ GlyphVector gv = commonSizeFont.createGlyphVector(frc, missingGlyphCode);
+ Shape missingGlyphShape = gv.getGlyphOutline(0);
+ GlyphMetrics gm = gv.getGlyphMetrics(0);
+
+ // need to turn the missing glyph upside down to be in the font
+ // coordinate system (i.e Y axis up)
+ AffineTransform at = AffineTransform.getScaleInstance(1, -1);
+ missingGlyphShape = at.createTransformedShape(missingGlyphShape);
+
+ missingGlyphElement.setAttributeNS(null, SVG_D_ATTRIBUTE,
+ SVGPath.toSVGPathData(missingGlyphShape));
+ missingGlyphElement.setAttributeNS(null, SVG_HORIZ_ADV_X_ATTRIBUTE,
+ "" + gm.getAdvance());
+ fontDef.appendChild(missingGlyphElement);
+
+ // set the font's default horizontal advance to be the same as
+ // the missing glyph
+ fontDef.setAttributeNS(null, SVG_HORIZ_ADV_X_ATTRIBUTE, "" + gm.getAdvance());
+
+ // set the ascent and descent attributes
+ LineMetrics lm = commonSizeFont.getLineMetrics("By", frc);
+ fontFace.setAttributeNS(null, SVG_ASCENT_ATTRIBUTE, "" + lm.getAscent());
+ fontFace.setAttributeNS(null, SVG_DESCENT_ATTRIBUTE, "" + lm.getDescent());
+
+ //
+ // Font ID
+ //
+ fontDef.setAttributeNS(null, ATTR_ID,
+ generatorContext.idGenerator.
+ generateID(ID_PREFIX_FONT));
+ }
+
+ //
+ // add any new glyphs to the fontDef here
+ //
+
+ // process the characters in textUsingFont backwards since the new chars
+ // are at the end, can stop when find a char that already has a glyph
+ for (int i = textUsingFont.length()-1; i >= 0; i--) {
+ char c = textUsingFont.charAt(i);
+ boolean foundGlyph = false;
+ NodeList fontChildren = fontDef.getChildNodes();
+ for (int j = 0; j < fontChildren.getLength(); j++) {
+ if (fontChildren.item(j) instanceof Element) {
+ Element childElement = (Element)fontChildren.item(j);
+ if (childElement.getAttributeNS(null,
+ SVG_UNICODE_ATTRIBUTE).equals(""+c)) {
+ foundGlyph = true;
+ break;
+ }
+ }
+ }
+ if (!foundGlyph) {
+ // need to create one
+ Element glyphElement
+ = domFactory.createElementNS(SVG_NAMESPACE_URI,
+ SVG_GLYPH_TAG);
+
+ GlyphVector gv = commonSizeFont.createGlyphVector(frc, ""+c);
+ Shape glyphShape = gv.getGlyphOutline(0);
+ GlyphMetrics gm = gv.getGlyphMetrics(0);
+
+ // need to turn the glyph upside down to be in the font
+ // coordinate system (i.e Y axis up)
+ AffineTransform at = AffineTransform.getScaleInstance(1, -1);
+ glyphShape = at.createTransformedShape(glyphShape);
+
+ glyphElement.setAttributeNS(null, SVG_D_ATTRIBUTE,
+ SVGPath.toSVGPathData(glyphShape));
+ glyphElement.setAttributeNS(null, SVG_HORIZ_ADV_X_ATTRIBUTE,
+ "" + gm.getAdvance());
+ glyphElement.setAttributeNS(null, SVG_UNICODE_ATTRIBUTE,
+ "" + c);
+
+ fontDef.appendChild(glyphElement);
+ } else {
+ // have reached the chars in textUsingFont that already
+ // have glyphs, don't need to process any further
+ break;
+ }
+ }
+
+ //
+ // create a new font description for this instance of the font usage
+ //
+ SVGFontDescriptor newFontDesc
+ = new SVGFontDescriptor(fontSize, fontWeight,
+ fontStyle, fontFamilyStr,
+ fontDef);
+
+ //
+ // Update maps so that the font def can be reused if needed
+ //
+ if (fontDesc == null) {
+ descMap.put(fontKey, newFontDesc);
+ defSet.add(fontDef);
+ }
+
+ return newFontDesc;
}
/**
1.4 +14 -2 xml-batik/sources/org/apache/batik/svggen/SVGFontDescriptor.java
Index: SVGFontDescriptor.java
===================================================================
RCS file: /home/cvs/xml-batik/sources/org/apache/batik/svggen/SVGFontDescriptor.java,v
retrieving revision 1.3
retrieving revision 1.4
diff -u -r1.3 -r1.4
--- SVGFontDescriptor.java 2001/04/26 14:17:19 1.3
+++ SVGFontDescriptor.java 2001/08/03 04:21:53 1.4
@@ -16,10 +16,13 @@
* Describes an SVG font
*
* @author <a href="mailto:vincent.hardy@eng.sun.com">Vincent Hardy</a>
- * @version $Id: SVGFontDescriptor.java,v 1.3 2001/04/26 14:17:19 cjolif Exp $
+ * @version $Id: SVGFontDescriptor.java,v 1.4 2001/08/03 04:21:53 bella Exp $
* @see org.apache.batik.svggen.SVGFont
*/
public class SVGFontDescriptor implements SVGDescriptor, SVGSyntax {
+
+ private Element def;
+
private String fontSize;
private String fontWeight;
private String fontStyle;
@@ -31,7 +34,8 @@
public SVGFontDescriptor(String fontSize,
String fontWeight,
String fontStyle,
- String fontFamily){
+ String fontFamily,
+ Element def){
if (fontSize == null ||
fontWeight == null ||
fontStyle == null ||
@@ -42,6 +46,7 @@
this.fontWeight = fontWeight;
this.fontStyle = fontStyle;
this.fontFamily = fontFamily;
+ this.def = def;
}
public Map getAttributeMap(Map attrMap){
@@ -56,9 +61,16 @@
return attrMap;
}
+ public Element getDef(){
+ return def;
+ }
+
public List getDefinitionSet(List defSet){
if (defSet == null)
defSet = new LinkedList();
+
+ if(def != null && !defSet.contains(def))
+ defSet.add(def);
return defSet;
}
1.10 +2 -2 xml-batik/sources/org/apache/batik/svggen/SVGGraphicContextConverter.java
Index: SVGGraphicContextConverter.java
===================================================================
RCS file: /home/cvs/xml-batik/sources/org/apache/batik/svggen/SVGGraphicContextConverter.java,v
retrieving revision 1.9
retrieving revision 1.10
diff -u -r1.9 -r1.10
--- SVGGraphicContextConverter.java 2001/04/26 14:17:21 1.9
+++ SVGGraphicContextConverter.java 2001/08/03 04:21:53 1.10
@@ -22,7 +22,7 @@
* SVG attributes.
*
* @author <a href="mailto:vincent.hardy@eng.sun.com">Vincent Hardy</a>
- * @version $Id: SVGGraphicContextConverter.java,v 1.9 2001/04/26 14:17:21 cjolif Exp $
+ * @version $Id: SVGGraphicContextConverter.java,v 1.10 2001/08/03 04:21:53 bella Exp $
*/
public class SVGGraphicContextConverter {
private static final int GRAPHIC_CONTEXT_CONVERTER_COUNT = 6;
@@ -59,7 +59,7 @@
compositeConverter = new SVGComposite(generatorContext);
clipConverter = new SVGClip(generatorContext);
hintsConverter = new SVGRenderingHints();
- fontConverter = new SVGFont();
+ fontConverter = new SVGFont(generatorContext);
int i=0;
converters[i++] = paintConverter;
1.20 +7 -1 xml-batik/sources/org/apache/batik/svggen/SVGGraphics2D.java
Index: SVGGraphics2D.java
===================================================================
RCS file: /home/cvs/xml-batik/sources/org/apache/batik/svggen/SVGGraphics2D.java,v
retrieving revision 1.19
retrieving revision 1.20
diff -u -r1.19 -r1.20
--- SVGGraphics2D.java 2001/06/21 07:54:30 1.19
+++ SVGGraphics2D.java 2001/08/03 04:21:53 1.20
@@ -44,7 +44,7 @@
*
*
* @author <a href="mailto:vincent.hardy@eng.sun.com">Vincent Hardy</a>
- * @version $Id: SVGGraphics2D.java,v 1.19 2001/06/21 07:54:30 cjolif Exp $
+ * @version $Id: SVGGraphics2D.java,v 1.20 2001/08/03 04:21:53 bella Exp $
* @see org.apache.batik.ext.awt.g2d.GraphicContext
* @see org.apache.batik.svggen.DOMTreeManager
* @see org.apache.batik.svggen.DOMGroupManager
@@ -968,6 +968,12 @@
*/
public void drawString(String s, float x, float y) {
if (!textAsShapes) {
+
+ // record that the font is being used to draw this string, this is
+ // so that the SVG Font element will only create glyphs for the
+ // characters that are needed
+ SVGFont.recordFontUsage(s, getFont());
+
Element text =
getDOMFactory().createElementNS(SVG_NAMESPACE_URI, SVG_TEXT_TAG);
text.setAttributeNS(null, SVG_X_ATTRIBUTE,
1.7 +4 -3 xml-batik/sources/org/apache/batik/svggen/SVGGraphics2DUnitTester.java
Index: SVGGraphics2DUnitTester.java
===================================================================
RCS file: /home/cvs/xml-batik/sources/org/apache/batik/svggen/SVGGraphics2DUnitTester.java,v
retrieving revision 1.6
retrieving revision 1.7
diff -u -r1.6 -r1.7
--- SVGGraphics2DUnitTester.java 2001/06/21 07:54:31 1.6
+++ SVGGraphics2DUnitTester.java 2001/08/03 04:21:53 1.7
@@ -31,7 +31,7 @@
*
* @author <a href="mailto:cjolif@ilog.fr">Christophe Jolif</a>
* @author <a href="mailto:vincent.hardy@eng.sun.com">Vincent Hardy</a>
- * @version $Id: SVGGraphics2DUnitTester.java,v 1.6 2001/06/21 07:54:31 cjolif Exp $
+ * @version $Id: SVGGraphics2DUnitTester.java,v 1.7 2001/08/03 04:21:53 bella Exp $
*/
public class SVGGraphics2DUnitTester implements SVGConstants {
private String[] args;
@@ -818,11 +818,12 @@
throws Exception {
Document domFactory = getDocumentPrototype();
Element group = domFactory.createElementNS(SVG_NAMESPACE_URI, SVG_G_TAG);
- SVGFont converter = new SVGFont();
+ SVGFont converter = new SVGFont(getContext(domFactory));
+ GraphicContext gc = new GraphicContext(new AffineTransform());
for(int i=0; i<fonts.length; i++){
Font font = fonts[i];
- Map attrMap = converter.toSVG(font).getAttributeMap(null);
+ Map attrMap = converter.toSVG(font, gc.getFontRenderContext()).getAttributeMap(null);
Element textElement = domFactory.createElementNS(SVG_NAMESPACE_URI, SVG_TEXT_TAG);
Iterator iter = attrMap.keySet().iterator();
while(iter.hasNext()){
1.5 +2 -1 xml-batik/sources/org/apache/batik/svggen/SVGSyntax.java
Index: SVGSyntax.java
===================================================================
RCS file: /home/cvs/xml-batik/sources/org/apache/batik/svggen/SVGSyntax.java,v
retrieving revision 1.4
retrieving revision 1.5
diff -u -r1.4 -r1.5
--- SVGSyntax.java 2001/03/26 09:45:16 1.4
+++ SVGSyntax.java 2001/08/03 04:21:53 1.5
@@ -14,7 +14,7 @@
* Contains the definition of the SVG tags and attribute names.
*
* @author <a href="mailto:vincent.hardy@eng.sun.com">Vincent Hardy</a>
- * @version $Id: SVGSyntax.java,v 1.4 2001/03/26 09:45:16 tkormann Exp $
+ * @version $Id: SVGSyntax.java,v 1.5 2001/08/03 04:21:53 bella Exp $
*/
public interface SVGSyntax extends SVGConstants{
/**
@@ -47,6 +47,7 @@
public static final String ID_PREFIX_FE_GAUSSIAN_BLUR = "feGaussianBlur";
public static final String ID_PREFIX_FE_LIGHTING_FILTER = "feLightingFilter";
public static final String ID_PREFIX_FE_SPECULAR_LIGHTING = "feSpecularLighting";
+ public static final String ID_PREFIX_FONT = "font";
public static final String ID_PREFIX_GENERIC_DEFS = "genericDefs";
public static final String ID_PREFIX_LINEAR_GRADIENT = "linearGradient";
public static final String ID_PREFIX_MASK = "mask";
---------------------------------------------------------------------
To unsubscribe, e-mail: batik-dev-unsubscribe@xml.apache.org
For additional commands, e-mail: batik-dev-help@xml.apache.org