001: /*
002:
003: Licensed to the Apache Software Foundation (ASF) under one or more
004: contributor license agreements. See the NOTICE file distributed with
005: this work for additional information regarding copyright ownership.
006: The ASF licenses this file to You under the Apache License, Version 2.0
007: (the "License"); you may not use this file except in compliance with
008: the License. You may obtain a copy of the License at
009:
010: http://www.apache.org/licenses/LICENSE-2.0
011:
012: Unless required by applicable law or agreed to in writing, software
013: distributed under the License is distributed on an "AS IS" BASIS,
014: WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
015: See the License for the specific language governing permissions and
016: limitations under the License.
017:
018: */
019: package org.apache.batik.bridge;
020:
021: import java.util.List;
022: import java.util.LinkedList;
023:
024: import org.w3c.dom.Element;
025: import org.w3c.dom.Node;
026:
027: import org.apache.batik.dom.AbstractNode;
028: import org.apache.batik.dom.util.XLinkSupport;
029: import org.apache.batik.util.ParsedURL;
030:
031: /**
032: * Bridge class for the <font-face> element.
033: *
034: * @author <a href="mailto:bella.robinson@cmis.csiro.au">Bella Robinson</a>
035: * @version $Id: SVGFontFaceElementBridge.java 502538 2007-02-02 08:52:56Z dvholten $
036: */
037: public class SVGFontFaceElementBridge extends AbstractSVGBridge
038: implements ErrorConstants {
039:
040: /**
041: * Constructs a new bridge for the <font-face> element.
042: */
043: public SVGFontFaceElementBridge() {
044: }
045:
046: /**
047: * Returns 'font-face'.
048: */
049: public String getLocalName() {
050: return SVG_FONT_FACE_TAG;
051: }
052:
053: /**
054: * Creates an SVGFontFace that repesents the specified
055: * <font-face> element.
056: *
057: * @param ctx The current bridge context.
058: * @param fontFaceElement The <font-face> element.
059: *
060: * @return A new SVGFontFace.
061: */
062: public SVGFontFace createFontFace(BridgeContext ctx,
063: Element fontFaceElement) {
064:
065: // get all the font-face attributes
066:
067: String familyNames = fontFaceElement.getAttributeNS(null,
068: SVG_FONT_FAMILY_ATTRIBUTE);
069:
070: // units per em
071: String unitsPerEmStr = fontFaceElement.getAttributeNS(null,
072: SVG_UNITS_PER_EM_ATTRIBUTE);
073: if (unitsPerEmStr.length() == 0) {
074: unitsPerEmStr = SVG_FONT_FACE_UNITS_PER_EM_DEFAULT_VALUE;
075: }
076: float unitsPerEm;
077: try {
078: unitsPerEm = SVGUtilities.convertSVGNumber(unitsPerEmStr);
079: } catch (NumberFormatException nfEx) {
080: throw new BridgeException(ctx, fontFaceElement, nfEx,
081: ERR_ATTRIBUTE_VALUE_MALFORMED, new Object[] {
082: SVG_UNITS_PER_EM_ATTRIBUTE, unitsPerEmStr });
083: }
084:
085: // font-weight
086: String fontWeight = fontFaceElement.getAttributeNS(null,
087: SVG_FONT_WEIGHT_ATTRIBUTE);
088: if (fontWeight.length() == 0) {
089: fontWeight = SVG_FONT_FACE_FONT_WEIGHT_DEFAULT_VALUE;
090: }
091:
092: // font-style
093: String fontStyle = fontFaceElement.getAttributeNS(null,
094: SVG_FONT_STYLE_ATTRIBUTE);
095: if (fontStyle.length() == 0) {
096: fontStyle = SVG_FONT_FACE_FONT_STYLE_DEFAULT_VALUE;
097: }
098:
099: // font-variant
100: String fontVariant = fontFaceElement.getAttributeNS(null,
101: SVG_FONT_VARIANT_ATTRIBUTE);
102: if (fontVariant.length() == 0) {
103: fontVariant = SVG_FONT_FACE_FONT_VARIANT_DEFAULT_VALUE;
104: }
105:
106: // font-stretch
107: String fontStretch = fontFaceElement.getAttributeNS(null,
108: SVG_FONT_STRETCH_ATTRIBUTE);
109: if (fontStretch.length() == 0) {
110: fontStretch = SVG_FONT_FACE_FONT_STRETCH_DEFAULT_VALUE;
111: }
112:
113: // slopeStr
114: String slopeStr = fontFaceElement.getAttributeNS(null,
115: SVG_SLOPE_ATTRIBUTE);
116: if (slopeStr.length() == 0) {
117: slopeStr = SVG_FONT_FACE_SLOPE_DEFAULT_VALUE;
118: }
119: float slope;
120: try {
121: slope = SVGUtilities.convertSVGNumber(slopeStr);
122: } catch (NumberFormatException nfEx) {
123: throw new BridgeException(ctx, fontFaceElement, nfEx,
124: ERR_ATTRIBUTE_VALUE_MALFORMED,
125: new Object[] { SVG_FONT_FACE_SLOPE_DEFAULT_VALUE,
126: slopeStr });
127: }
128:
129: // panose-1
130: String panose1 = fontFaceElement.getAttributeNS(null,
131: SVG_PANOSE_1_ATTRIBUTE);
132: if (panose1.length() == 0) {
133: panose1 = SVG_FONT_FACE_PANOSE_1_DEFAULT_VALUE;
134: }
135:
136: // ascent
137: String ascentStr = fontFaceElement.getAttributeNS(null,
138: SVG_ASCENT_ATTRIBUTE);
139: if (ascentStr.length() == 0) {
140: // set it to be unitsPerEm * .8
141: ascentStr = String.valueOf(unitsPerEm * 0.8);
142: }
143: float ascent;
144: try {
145: ascent = SVGUtilities.convertSVGNumber(ascentStr);
146: } catch (NumberFormatException nfEx) {
147: throw new BridgeException(ctx, fontFaceElement, nfEx,
148: ERR_ATTRIBUTE_VALUE_MALFORMED, new Object[] {
149: SVG_FONT_FACE_SLOPE_DEFAULT_VALUE,
150: ascentStr });
151: }
152:
153: // descent
154: String descentStr = fontFaceElement.getAttributeNS(null,
155: SVG_DESCENT_ATTRIBUTE);
156: if (descentStr.length() == 0) {
157: // set it to be unitsPerEm *.2.
158: descentStr = String.valueOf(unitsPerEm * 0.2);
159: }
160: float descent;
161: try {
162: descent = SVGUtilities.convertSVGNumber(descentStr);
163: } catch (NumberFormatException nfEx) {
164: throw new BridgeException(ctx, fontFaceElement, nfEx,
165: ERR_ATTRIBUTE_VALUE_MALFORMED, new Object[] {
166: SVG_FONT_FACE_SLOPE_DEFAULT_VALUE,
167: descentStr });
168: }
169:
170: // underline-position
171: String underlinePosStr = fontFaceElement.getAttributeNS(null,
172: SVG_UNDERLINE_POSITION_ATTRIBUTE);
173: if (underlinePosStr.length() == 0) {
174: underlinePosStr = String.valueOf(-3 * unitsPerEm / 40);
175: }
176: float underlinePos;
177: try {
178: underlinePos = SVGUtilities
179: .convertSVGNumber(underlinePosStr);
180: } catch (NumberFormatException nfEx) {
181: throw new BridgeException(ctx, fontFaceElement, nfEx,
182: ERR_ATTRIBUTE_VALUE_MALFORMED, new Object[] {
183: SVG_FONT_FACE_SLOPE_DEFAULT_VALUE,
184: underlinePosStr });
185: }
186:
187: // underline-thickness
188: String underlineThicknessStr = fontFaceElement.getAttributeNS(
189: null, SVG_UNDERLINE_THICKNESS_ATTRIBUTE);
190: if (underlineThicknessStr.length() == 0) {
191: underlineThicknessStr = String.valueOf(unitsPerEm / 20);
192: }
193: float underlineThickness;
194: try {
195: underlineThickness = SVGUtilities
196: .convertSVGNumber(underlineThicknessStr);
197: } catch (NumberFormatException nfEx) {
198: throw new BridgeException(ctx, fontFaceElement, nfEx,
199: ERR_ATTRIBUTE_VALUE_MALFORMED, new Object[] {
200: SVG_FONT_FACE_SLOPE_DEFAULT_VALUE,
201: underlineThicknessStr });
202: }
203:
204: // strikethrough-position
205: String strikethroughPosStr = fontFaceElement.getAttributeNS(
206: null, SVG_STRIKETHROUGH_POSITION_ATTRIBUTE);
207: if (strikethroughPosStr.length() == 0) {
208: strikethroughPosStr = String.valueOf(3 * ascent / 8);
209: }
210: float strikethroughPos;
211: try {
212: strikethroughPos = SVGUtilities
213: .convertSVGNumber(strikethroughPosStr);
214: } catch (NumberFormatException nfEx) {
215: throw new BridgeException(ctx, fontFaceElement, nfEx,
216: ERR_ATTRIBUTE_VALUE_MALFORMED, new Object[] {
217: SVG_FONT_FACE_SLOPE_DEFAULT_VALUE,
218: strikethroughPosStr });
219: }
220:
221: // strikethrough-thickness
222: String strikethroughThicknessStr = fontFaceElement
223: .getAttributeNS(null,
224: SVG_STRIKETHROUGH_THICKNESS_ATTRIBUTE);
225: if (strikethroughThicknessStr.length() == 0) {
226: strikethroughThicknessStr = String.valueOf(unitsPerEm / 20);
227: }
228: float strikethroughThickness;
229: try {
230: strikethroughThickness = SVGUtilities
231: .convertSVGNumber(strikethroughThicknessStr);
232: } catch (NumberFormatException nfEx) {
233: throw new BridgeException(ctx, fontFaceElement, nfEx,
234: ERR_ATTRIBUTE_VALUE_MALFORMED, new Object[] {
235: SVG_FONT_FACE_SLOPE_DEFAULT_VALUE,
236: strikethroughThicknessStr });
237: }
238:
239: // overline-position
240: String overlinePosStr = fontFaceElement.getAttributeNS(null,
241: SVG_OVERLINE_POSITION_ATTRIBUTE);
242: if (overlinePosStr.length() == 0) {
243: overlinePosStr = String.valueOf(ascent);
244: }
245: float overlinePos;
246: try {
247: overlinePos = SVGUtilities.convertSVGNumber(overlinePosStr);
248: } catch (NumberFormatException nfEx) {
249: throw new BridgeException(ctx, fontFaceElement, nfEx,
250: ERR_ATTRIBUTE_VALUE_MALFORMED, new Object[] {
251: SVG_FONT_FACE_SLOPE_DEFAULT_VALUE,
252: overlinePosStr });
253: }
254:
255: // overline-thickness
256: String overlineThicknessStr = fontFaceElement.getAttributeNS(
257: null, SVG_OVERLINE_THICKNESS_ATTRIBUTE);
258: if (overlineThicknessStr.length() == 0) {
259: overlineThicknessStr = String.valueOf(unitsPerEm / 20);
260: }
261: float overlineThickness;
262: try {
263: overlineThickness = SVGUtilities
264: .convertSVGNumber(overlineThicknessStr);
265: } catch (NumberFormatException nfEx) {
266: throw new BridgeException(ctx, fontFaceElement, nfEx,
267: ERR_ATTRIBUTE_VALUE_MALFORMED, new Object[] {
268: SVG_FONT_FACE_SLOPE_DEFAULT_VALUE,
269: overlineThicknessStr });
270: }
271:
272: List srcs = null;
273: Element fontElt = SVGUtilities
274: .getParentElement(fontFaceElement);
275: if (!fontElt.getNamespaceURI().equals(SVG_NAMESPACE_URI)
276: || !fontElt.getLocalName().equals(SVG_FONT_TAG)) {
277: srcs = getFontFaceSrcs(fontFaceElement);
278: }
279:
280: // TODO: get the rest of the attributes
281: return new SVGFontFace(fontFaceElement, srcs, familyNames,
282: unitsPerEm, fontWeight, fontStyle, fontVariant,
283: fontStretch, slope, panose1, ascent, descent,
284: strikethroughPos, strikethroughThickness, underlinePos,
285: underlineThickness, overlinePos, overlineThickness);
286: }
287:
288: /**
289: * the returned list may contain Strings and ParsedURLs
290: */
291: public List getFontFaceSrcs(Element fontFaceElement) {
292: // Search for a font-face-src element
293: Element ffsrc = null;
294: for (Node n = fontFaceElement.getFirstChild(); n != null; n = n
295: .getNextSibling()) {
296: if ((n.getNodeType() == Node.ELEMENT_NODE)
297: && n.getNamespaceURI().equals(SVG_NAMESPACE_URI)
298: && n.getLocalName().equals(SVG_FONT_FACE_SRC_TAG)) {
299: ffsrc = (Element) n;
300: break;
301: }
302: }
303: if (ffsrc == null)
304: return null;
305:
306: List ret = new LinkedList();
307:
308: // Search for a font-face-uri, or font-face-name elements
309: for (Node n = ffsrc.getFirstChild(); n != null; n = n
310: .getNextSibling()) {
311: if ((n.getNodeType() != Node.ELEMENT_NODE)
312: || !n.getNamespaceURI().equals(SVG_NAMESPACE_URI))
313: continue;
314:
315: if (n.getLocalName().equals(SVG_FONT_FACE_URI_TAG)) {
316: Element ffuri = (Element) n;
317: String uri = XLinkSupport.getXLinkHref(ffuri);
318: String base = AbstractNode.getBaseURI(ffuri);
319: ParsedURL purl;
320: if (base != null)
321: purl = new ParsedURL(base, uri);
322: else
323: purl = new ParsedURL(uri);
324: ret.add(purl); // here we add a ParsedURL
325: continue;
326: }
327: if (n.getLocalName().equals(SVG_FONT_FACE_NAME_TAG)) {
328: Element ffname = (Element) n;
329: String s = ffname.getAttribute("name");
330: if (s.length() != 0)
331: ret.add(s); // here we add a String
332: }
333: }
334: return ret;
335: }
336: }
|