001: /*
002: *
003: *
004: * Copyright 1990-2007 Sun Microsystems, Inc. All Rights Reserved.
005: * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER
006: *
007: * This program is free software; you can redistribute it and/or
008: * modify it under the terms of the GNU General Public License version
009: * 2 only, as published by the Free Software Foundation.
010: *
011: * This program is distributed in the hope that it will be useful, but
012: * WITHOUT ANY WARRANTY; without even the implied warranty of
013: * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
014: * General Public License version 2 for more details (a copy is
015: * included at /legal/license.txt).
016: *
017: * You should have received a copy of the GNU General Public License
018: * version 2 along with this work; if not, write to the Free Software
019: * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
020: * 02110-1301 USA
021: *
022: * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa
023: * Clara, CA 95054 or visit www.sun.com if you need additional
024: * information or have any questions.
025: */
026: package com.sun.perseus.builder;
027:
028: import com.sun.perseus.model.FontFace;
029: import com.sun.perseus.model.ModelNode;
030: import com.sun.perseus.model.UpdateAdapter;
031: import com.sun.perseus.model.DocumentNode;
032:
033: import com.sun.perseus.platform.ResourceHandler;
034:
035: import java.io.InputStream;
036: import java.io.IOException;
037: import java.io.Reader;
038:
039: import javax.xml.parsers.SAXParserFactory;
040: import javax.xml.parsers.SAXParser;
041:
042: /**
043: * This helper class encapsulates the creation of a default <tt>FontFace</tt>
044: * which a renderer can use. <br />
045: *
046: * This class tries to load an SVG file containing a font. The resource
047: * identifier for the default font is: <br />
048: * <tt>com/sun/perseus/renderer/resources/defaultFont.svg</tt><br />
049: *
050: * <b>Note</b>: the <tt>defaultFont.svg</tt> is loaded and its first
051: * <tt><font></tt> element is loaded. The first <tt><font></tt>
052: * element must be the first child of the root <tt><svg></tt> element. Any
053: * other structure for the <tt>defaultFont.svg</tt> file will result in an
054: * <tt>Error</tt>.
055: *
056: * This helper class also encapsulates the creation and loading of a set
057: * of <tt>FontFaces</tt> for the initial font-family value. The fonts are
058: * expected to all be in a single initial font file: <br />
059: * <tt>com/sun/perseus/renderer/resources/initialFont.svg</tt>
060: *
061: *
062: * <b>Note</b>: the <tt>initialFont.svg</tt> is loaded and all the
063: * children of the root <tt><svg></tt> element are expected to
064: * be <tt><font></tt> elements. Any
065: * other structure for the <tt>initialFont.svg</tt> file will result in an
066: * <tt>Error</tt>.
067: *
068: * @see com.sun.perseus.render.RenderGraphics
069: *
070: * @version $Id: DefaultFontFace.java,v 1.6 2006/07/17 00:35:43 st125089 Exp $
071: */
072: public final class DefaultFontFace {
073:
074: /**
075: * The default font face is cached so that it is loaded only
076: * once
077: */
078: protected static FontFace defaultFontFace;
079:
080: /**
081: * The set of initial font faces is cached so that it is loaded
082: * only once.
083: */
084: protected static FontFace[] initialFontFaces;
085:
086: /**
087: * @return the default font face. This font face is loaded from the
088: * {@link #ResourceHandler.DEFAULT_FONT_FACE_FILE
089: * ResourceHandler.DEFAULT_FONT_FACE} resource.
090: */
091: public static FontFace getDefaultFontFace() {
092: if (defaultFontFace == null) {
093: loadDefaultFontFace();
094: }
095: return defaultFontFace;
096: }
097:
098: /**
099: * @return the initial font faces. The initial font faces are
100: * loaded from the
101: * {@link #ResourceHandler.INITIAL_FONT_FACE_FILE
102: * ResourceHandler.INITIAL_FONT_FACE_FILE} resource.
103: */
104: public static FontFace[] getInitialFontFaces() {
105: if (initialFontFaces == null) {
106: loadInitialFontFaces();
107: }
108: return initialFontFaces;
109: }
110:
111: /**
112: * Loads the initial font faces. This assumes that the font face file
113: * has not been loaded already. If the load of the font face fails, the
114: * application throws an error.
115: *
116: * @throws Error if there is an error while loading the file. An error
117: * is generated.
118: * @see #getInitialFontFaces
119: */
120: static void loadInitialFontFaces() throws Error {
121: try {
122: InputStream is = ResourceHandler.getInitialFontResource();
123: if (is == null) {
124: throw new Exception(Messages.formatMessage(
125: Messages.ERROR_CANNOT_LOAD_RESOURCE,
126: new Object[] { "Initial Font" }));
127: }
128:
129: ModelNode svg = loadSVGFontResource(is);
130:
131: // Now, get the FontFace from the tree.
132: // vp -> svg -> font[i] -> font-face
133:
134: // Count the font children
135: int n = 0;
136: ModelNode c = svg.getFirstChildNode();
137: while (c != null) {
138: n++;
139: c = c.getNextSiblingNode();
140: }
141: initialFontFaces = new FontFace[n];
142: ModelNode font = svg.getFirstChildNode();
143: for (int i = 0; i < initialFontFaces.length; i++) {
144: initialFontFaces[i] = (FontFace) font
145: .getFirstChildNode();
146: font = font.getNextSiblingNode();
147: }
148: } catch (Exception e) {
149: // Do not tolerate any error as this is critical for the operation
150: // of the toolkit.
151: e.printStackTrace();
152: throw new Error();
153: }
154: }
155:
156: /**
157: * Loads the default font face. This assumes that the font face file
158: * has not been loaded already. If the load of the font face fails, the
159: * application throws an error.
160: *
161: * @throws Error if there is an error while loading the default font
162: * face file.
163: * @see #getDefaultFontFace
164: */
165: static void loadDefaultFontFace() throws Error {
166: try {
167: InputStream is = ResourceHandler.getDefaultFontResource();
168: if (is == null) {
169: throw new Exception(Messages.formatMessage(
170: Messages.ERROR_CANNOT_LOAD_RESOURCE,
171: new Object[] { "Default Font" }));
172: }
173:
174: ModelNode svg = loadSVGFontResource(is);
175:
176: // Now, get the FontFace from the tree.
177: // svg -> font -> font-face
178: defaultFontFace = (FontFace) svg.getFirstChildNode()
179: .getFirstChildNode();
180:
181: } catch (Exception e) {
182: // Do not tolerate any error as this is critical for the operation
183: // of the toolkit.
184: e.printStackTrace();
185: throw new Error();
186: }
187: }
188:
189: /**
190: * Helper method: loads an SVG Font resource file
191: * @param svgResource the SVG Font resource file
192: * @return The root <tt><svg></tt> element representing the
193: * resource file.
194: * @throws Exception if an error happens while loading the resource
195: */
196: protected static ModelNode loadSVGFontResource(final InputStream is)
197: throws Exception {
198: // We use JAXP to get a SAX 2 Parser
199: SAXParserFactory factory = SAXParserFactory.newInstance();
200: factory.setNamespaceAware(true);
201: factory.setValidating(true);
202: SAXParser parser = factory.newSAXParser();
203:
204: // Configure a ModelBuilder to turn an SVG document
205: // into a ModelNode tree
206: DocumentNode root = new DocumentNode();
207: UpdateAdapter ul = new UpdateAdapter();
208: root.setUpdateListener(ul);
209: ModelBuilder modelBuilder = new ModelBuilder(null, root);
210:
211: ul.loadStarting(root, is);
212:
213: try {
214: parser.parse(is, modelBuilder);
215: } finally {
216: try {
217: is.close();
218: } catch (IOException ioe) {
219: }
220:
221: int n = modelBuilder.entityStreams.size();
222: for (int i = 0; i < n; i++) {
223: Reader r = (Reader) modelBuilder.entityStreams
224: .elementAt(i);
225: try {
226: r.close();
227: } catch (IOException ioe) {
228: // Do nothing: this means the stream was
229: // closed by the SAX parser.
230: }
231: }
232: }
233:
234: if (!ul.loadSuccess()) {
235: throw new Exception(Messages.formatMessage(
236: Messages.ERROR_CANNOT_LOAD_RESOURCE,
237: new Object[] { "SVG System Font Resource" }));
238: }
239:
240: // trace(modelBuilder.getModelRoot(), "");
241: return modelBuilder.getModelRoot().getFirstChildNode();
242: }
243:
244: /**
245: * Private default constructor to prevent instantiation of this
246: * utility class
247: */
248: private DefaultFontFace() {
249: }
250: }
|