blob: 732510a5067c3898ccdd0fa25ad9ba191879f89f [file] [log] [blame]
/*
Licensed to the Apache Software Foundation (ASF) under one or more
contributor license agreements. See the NOTICE file distributed with
this work for additional information regarding copyright ownership.
The ASF licenses this file to You under the Apache License, Version 2.0
(the "License"); you may not use this file except in compliance with
the License. You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
*/
package org.apache.batik.bridge;
import java.util.List;
import java.util.LinkedList;
import org.w3c.dom.Element;
import org.w3c.dom.Node;
import org.apache.batik.dom.AbstractNode;
import org.apache.batik.dom.util.XLinkSupport;
import org.apache.batik.util.ParsedURL;
/**
* Bridge class for the <font-face> element.
*
* @author <a href="mailto:bella.robinson@cmis.csiro.au">Bella Robinson</a>
* @version $Id$
*/
public class SVGFontFaceElementBridge extends AbstractSVGBridge
implements ErrorConstants {
/**
* Constructs a new bridge for the &lt;font-face&gt; element.
*/
public SVGFontFaceElementBridge() {
}
/**
* Returns 'font-face'.
*/
public String getLocalName() {
return SVG_FONT_FACE_TAG;
}
/**
* Creates an SVGFontFace that repesents the specified
* &lt;font-face&gt; element.
*
* @param ctx The current bridge context.
* @param fontFaceElement The &lt;font-face&gt; element.
*
* @return A new SVGFontFace.
*/
public SVGFontFace createFontFace(BridgeContext ctx,
Element fontFaceElement) {
// get all the font-face attributes
String familyNames = fontFaceElement.getAttributeNS
(null, SVG_FONT_FAMILY_ATTRIBUTE);
// units per em
String unitsPerEmStr = fontFaceElement.getAttributeNS
(null, SVG_UNITS_PER_EM_ATTRIBUTE);
if (unitsPerEmStr.length() == 0) {
unitsPerEmStr = SVG_FONT_FACE_UNITS_PER_EM_DEFAULT_VALUE;
}
float unitsPerEm;
try {
unitsPerEm = SVGUtilities.convertSVGNumber(unitsPerEmStr);
} catch (NumberFormatException nfEx ) {
throw new BridgeException
(ctx, fontFaceElement, nfEx, ERR_ATTRIBUTE_VALUE_MALFORMED,
new Object [] {SVG_UNITS_PER_EM_ATTRIBUTE, unitsPerEmStr});
}
// font-weight
String fontWeight = fontFaceElement.getAttributeNS
(null, SVG_FONT_WEIGHT_ATTRIBUTE);
if (fontWeight.length() == 0) {
fontWeight = SVG_FONT_FACE_FONT_WEIGHT_DEFAULT_VALUE;
}
// font-style
String fontStyle = fontFaceElement.getAttributeNS
(null, SVG_FONT_STYLE_ATTRIBUTE);
if (fontStyle.length() == 0) {
fontStyle = SVG_FONT_FACE_FONT_STYLE_DEFAULT_VALUE;
}
// font-variant
String fontVariant = fontFaceElement.getAttributeNS
(null, SVG_FONT_VARIANT_ATTRIBUTE);
if (fontVariant.length() == 0) {
fontVariant = SVG_FONT_FACE_FONT_VARIANT_DEFAULT_VALUE;
}
// font-stretch
String fontStretch = fontFaceElement.getAttributeNS
(null, SVG_FONT_STRETCH_ATTRIBUTE);
if (fontStretch.length() == 0) {
fontStretch = SVG_FONT_FACE_FONT_STRETCH_DEFAULT_VALUE;
}
// slopeStr
String slopeStr = fontFaceElement.getAttributeNS
(null, SVG_SLOPE_ATTRIBUTE);
if (slopeStr.length() == 0) {
slopeStr = SVG_FONT_FACE_SLOPE_DEFAULT_VALUE;
}
float slope;
try {
slope = SVGUtilities.convertSVGNumber(slopeStr);
} catch (NumberFormatException nfEx ) {
throw new BridgeException
(ctx, fontFaceElement, nfEx, ERR_ATTRIBUTE_VALUE_MALFORMED,
new Object [] {SVG_FONT_FACE_SLOPE_DEFAULT_VALUE, slopeStr});
}
// panose-1
String panose1 = fontFaceElement.getAttributeNS
(null, SVG_PANOSE_1_ATTRIBUTE);
if (panose1.length() == 0) {
panose1 = SVG_FONT_FACE_PANOSE_1_DEFAULT_VALUE;
}
// ascent
String ascentStr = fontFaceElement.getAttributeNS
(null, SVG_ASCENT_ATTRIBUTE);
if (ascentStr.length() == 0) {
// set it to be unitsPerEm * .8
ascentStr = String.valueOf( unitsPerEm * 0.8);
}
float ascent;
try {
ascent = SVGUtilities.convertSVGNumber(ascentStr);
} catch (NumberFormatException nfEx ) {
throw new BridgeException
(ctx, fontFaceElement, nfEx, ERR_ATTRIBUTE_VALUE_MALFORMED,
new Object [] {SVG_FONT_FACE_SLOPE_DEFAULT_VALUE, ascentStr});
}
// descent
String descentStr = fontFaceElement.getAttributeNS
(null, SVG_DESCENT_ATTRIBUTE);
if (descentStr.length() == 0) {
// set it to be unitsPerEm *.2.
descentStr = String.valueOf(unitsPerEm*0.2);
}
float descent;
try {
descent = SVGUtilities.convertSVGNumber(descentStr);
} catch (NumberFormatException nfEx ) {
throw new BridgeException
(ctx, fontFaceElement, nfEx, ERR_ATTRIBUTE_VALUE_MALFORMED,
new Object [] {SVG_FONT_FACE_SLOPE_DEFAULT_VALUE, descentStr });
}
// underline-position
String underlinePosStr = fontFaceElement.getAttributeNS
(null, SVG_UNDERLINE_POSITION_ATTRIBUTE);
if (underlinePosStr.length() == 0) {
underlinePosStr = String.valueOf(-3*unitsPerEm/40);
}
float underlinePos;
try {
underlinePos = SVGUtilities.convertSVGNumber(underlinePosStr);
} catch (NumberFormatException nfEx ) {
throw new BridgeException
(ctx, fontFaceElement, nfEx, ERR_ATTRIBUTE_VALUE_MALFORMED,
new Object [] {SVG_FONT_FACE_SLOPE_DEFAULT_VALUE,
underlinePosStr});
}
// underline-thickness
String underlineThicknessStr = fontFaceElement.getAttributeNS
(null, SVG_UNDERLINE_THICKNESS_ATTRIBUTE);
if (underlineThicknessStr.length() == 0) {
underlineThicknessStr = String.valueOf(unitsPerEm/20);
}
float underlineThickness;
try {
underlineThickness =
SVGUtilities.convertSVGNumber(underlineThicknessStr);
} catch (NumberFormatException nfEx ) {
throw new BridgeException
(ctx, fontFaceElement, nfEx, ERR_ATTRIBUTE_VALUE_MALFORMED,
new Object [] {SVG_FONT_FACE_SLOPE_DEFAULT_VALUE,
underlineThicknessStr});
}
// strikethrough-position
String strikethroughPosStr = fontFaceElement.getAttributeNS
(null, SVG_STRIKETHROUGH_POSITION_ATTRIBUTE);
if (strikethroughPosStr.length() == 0) {
strikethroughPosStr = String.valueOf(3*ascent/8);
}
float strikethroughPos;
try {
strikethroughPos =
SVGUtilities.convertSVGNumber(strikethroughPosStr);
} catch (NumberFormatException nfEx ) {
throw new BridgeException
(ctx, fontFaceElement, nfEx, ERR_ATTRIBUTE_VALUE_MALFORMED,
new Object [] {SVG_FONT_FACE_SLOPE_DEFAULT_VALUE,
strikethroughPosStr});
}
// strikethrough-thickness
String strikethroughThicknessStr = fontFaceElement.getAttributeNS
(null, SVG_STRIKETHROUGH_THICKNESS_ATTRIBUTE);
if (strikethroughThicknessStr.length() == 0) {
strikethroughThicknessStr = String.valueOf(unitsPerEm/20);
}
float strikethroughThickness;
try {
strikethroughThickness =
SVGUtilities.convertSVGNumber(strikethroughThicknessStr);
} catch (NumberFormatException nfEx ) {
throw new BridgeException
(ctx, fontFaceElement, nfEx, ERR_ATTRIBUTE_VALUE_MALFORMED,
new Object [] {SVG_FONT_FACE_SLOPE_DEFAULT_VALUE,
strikethroughThicknessStr});
}
// overline-position
String overlinePosStr = fontFaceElement.getAttributeNS
(null, SVG_OVERLINE_POSITION_ATTRIBUTE);
if (overlinePosStr.length() == 0) {
overlinePosStr = String.valueOf(ascent);
}
float overlinePos;
try {
overlinePos = SVGUtilities.convertSVGNumber(overlinePosStr);
} catch (NumberFormatException nfEx ) {
throw new BridgeException
(ctx, fontFaceElement, nfEx, ERR_ATTRIBUTE_VALUE_MALFORMED,
new Object [] {SVG_FONT_FACE_SLOPE_DEFAULT_VALUE,
overlinePosStr});
}
// overline-thickness
String overlineThicknessStr = fontFaceElement.getAttributeNS
(null, SVG_OVERLINE_THICKNESS_ATTRIBUTE);
if (overlineThicknessStr.length() == 0) {
overlineThicknessStr = String.valueOf(unitsPerEm/20);
}
float overlineThickness;
try {
overlineThickness =
SVGUtilities.convertSVGNumber(overlineThicknessStr);
} catch (NumberFormatException nfEx ) {
throw new BridgeException
(ctx, fontFaceElement, nfEx, ERR_ATTRIBUTE_VALUE_MALFORMED,
new Object [] {SVG_FONT_FACE_SLOPE_DEFAULT_VALUE,
overlineThicknessStr});
}
List srcs = null;
Element fontElt = SVGUtilities.getParentElement(fontFaceElement);
if (!fontElt.getNamespaceURI().equals(SVG_NAMESPACE_URI) ||
!fontElt.getLocalName().equals(SVG_FONT_TAG)) {
srcs = getFontFaceSrcs(fontFaceElement);
}
// TODO: get the rest of the attributes
return new SVGFontFace(fontFaceElement, srcs,
familyNames, unitsPerEm, fontWeight, fontStyle,
fontVariant, fontStretch, slope, panose1,
ascent, descent, strikethroughPos,
strikethroughThickness, underlinePos,
underlineThickness, overlinePos,
overlineThickness);
}
/**
* the returned list may contain Strings and ParsedURLs
*/
public List getFontFaceSrcs(Element fontFaceElement) {
// Search for a font-face-src element
Element ffsrc = null;
for (Node n = fontFaceElement.getFirstChild();
n != null;
n = n.getNextSibling()) {
if ((n.getNodeType() == Node.ELEMENT_NODE) &&
n.getNamespaceURI().equals(SVG_NAMESPACE_URI) &&
n.getLocalName().equals(SVG_FONT_FACE_SRC_TAG)) {
ffsrc = (Element)n;
break;
}
}
if (ffsrc == null)
return null;
List ret = new LinkedList();
// Search for a font-face-uri, or font-face-name elements
for (Node n = ffsrc.getFirstChild();
n != null;
n = n.getNextSibling()) {
if ((n.getNodeType() != Node.ELEMENT_NODE) ||
!n.getNamespaceURI().equals(SVG_NAMESPACE_URI))
continue;
if (n.getLocalName().equals(SVG_FONT_FACE_URI_TAG)) {
Element ffuri = (Element)n;
String uri = XLinkSupport.getXLinkHref(ffuri);
String base = AbstractNode.getBaseURI(ffuri);
ParsedURL purl;
if (base != null) purl = new ParsedURL(base, uri);
else purl = new ParsedURL(uri);
ret.add(purl); // here we add a ParsedURL
continue;
}
if (n.getLocalName().equals(SVG_FONT_FACE_NAME_TAG)) {
Element ffname = (Element)n;
String s = ffname.getAttribute("name");
if (s.length() != 0)
ret.add(s); // here we add a String
}
}
return ret;
}
}