001: /*
002: * Licensed to the Apache Software Foundation (ASF) under one or more
003: * contributor license agreements. See the NOTICE file distributed with
004: * this work for additional information regarding copyright ownership.
005: * The ASF licenses this file to You under the Apache License, Version 2.0
006: * (the "License"); you may not use this file except in compliance with
007: * the License. You may obtain a copy of the License at
008: *
009: * http://www.apache.org/licenses/LICENSE-2.0
010: *
011: * Unless required by applicable law or agreed to in writing, software
012: * distributed under the License is distributed on an "AS IS" BASIS,
013: * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
014: * See the License for the specific language governing permissions and
015: * limitations under the License.
016: */
017:
018: /* $Id: RasterFont.java 426576 2006-07-28 15:44:37Z jeremias $ */
019:
020: package org.apache.fop.render.afp.fonts;
021:
022: import java.util.HashMap;
023: import java.util.Iterator;
024: import java.util.Map;
025:
026: import org.apache.commons.logging.Log;
027: import org.apache.commons.logging.LogFactory;
028: import org.apache.fop.render.afp.exceptions.FontRuntimeException;
029:
030: /**
031: * A font where each character is stored as an array of pixels (a bitmap). Such
032: * fonts are not easily scalable, in contrast to vectored fonts. With this type
033: * of font, the font metrics information is held in character set files (one for
034: * each size and style). <p/>
035: *
036: */
037: public class RasterFont extends AFPFont {
038:
039: /** Static logging instance */
040: protected static final Log log = LogFactory
041: .getLog("org.apache.fop.render.afp.fonts");
042:
043: private HashMap _characterSets = new HashMap();
044:
045: private CharacterSet _characterSet = null;
046:
047: /**
048: * Constructor for the raster font requires the name, weight and style
049: * attribute to be available as this forms the key to the font.
050: *
051: * @param name
052: * the name of the font
053: */
054: public RasterFont(String name) {
055: super (name);
056: }
057:
058: public void addCharacterSet(int size, CharacterSet characterSet) {
059:
060: _characterSets.put(String.valueOf(size), characterSet);
061:
062: _characterSet = characterSet;
063:
064: }
065:
066: /**
067: * Get the character set metrics for the specified point size.
068: *
069: * @param size the point size
070: * @return the character set metrics
071: */
072: public CharacterSet getCharacterSet(int size) {
073:
074: String pointsize = String.valueOf(size / 1000);
075: CharacterSet csm = (CharacterSet) _characterSets.get(pointsize);
076: if (csm == null) {
077: csm = (CharacterSet) _characterSets.get(size + "mpt");
078: }
079: if (csm == null) {
080: // Get char set with nearest font size
081: int distance = Integer.MAX_VALUE;
082: for (Iterator it = _characterSets.entrySet().iterator(); it
083: .hasNext();) {
084: Map.Entry me = (Map.Entry) it.next();
085: String key = (String) me.getKey();
086: if (!key.endsWith("mpt")) {
087: int mpt = Integer.parseInt(key) * 1000;
088: if (Math.abs(size - mpt) < distance) {
089: distance = Math.abs(size - mpt);
090: pointsize = (String) me.getKey();
091: csm = (CharacterSet) me.getValue();
092: }
093: }
094: }
095: if (csm != null) {
096: _characterSets.put(size + "mpt", csm);
097: String msg = "No " + (size / 1000) + "pt font " + _name
098: + " found, substituted with " + pointsize
099: + "pt font";
100: log.warn(msg);
101: }
102: }
103: if (csm == null) {
104: String msg = "No font found for font " + _name
105: + " with point size " + pointsize;
106: log.error(msg);
107: throw new FontRuntimeException(msg);
108: }
109: return csm;
110:
111: }
112:
113: /**
114: * Get the first character in this font.
115: */
116: public int getFirstChar() {
117:
118: Iterator i = _characterSets.values().iterator();
119: if (i.hasNext()) {
120: CharacterSet csm = (CharacterSet) i.next();
121: return csm.getFirstChar();
122: } else {
123: String msg = "getFirstChar() - No character set found for font:"
124: + _name;
125: log.error(msg);
126: throw new FontRuntimeException(msg);
127: }
128:
129: }
130:
131: /**
132: * Get the last character in this font.
133: */
134: public int getLastChar() {
135:
136: Iterator i = _characterSets.values().iterator();
137: if (i.hasNext()) {
138: CharacterSet csm = (CharacterSet) i.next();
139: return csm.getLastChar();
140: } else {
141: String msg = "getLastChar() - No character set found for font:"
142: + _name;
143: log.error(msg);
144: throw new FontRuntimeException(msg);
145: }
146:
147: }
148:
149: /**
150: * The ascender is the part of a lowercase letter that extends above the
151: * "x-height" (the height of the letter "x"), such as "d", "t", or "h". Also
152: * used to denote the part of the letter extending above the x-height.
153: *
154: * @param size the point size
155: */
156: public int getAscender(int size) {
157:
158: return getCharacterSet(size).getAscender();
159:
160: }
161:
162: /**
163: * Obtains the height of capital letters for the specified point size.
164: *
165: * @param size the point size
166: */
167: public int getCapHeight(int size) {
168:
169: return getCharacterSet(size).getCapHeight();
170:
171: }
172:
173: /**
174: * The descender is the part of a lowercase letter that extends below the
175: * base line, such as "g", "j", or "p". Also used to denote the part of the
176: * letter extending below the base line.
177: *
178: * @param size the point size
179: */
180: public int getDescender(int size) {
181:
182: return getCharacterSet(size).getDescender();
183:
184: }
185:
186: /**
187: * The "x-height" (the height of the letter "x").
188: *
189: * @param size the point size
190: */
191: public int getXHeight(int size) {
192:
193: return getCharacterSet(size).getXHeight();
194:
195: }
196:
197: /**
198: * Obtain the width of the character for the specified point size.
199: */
200: public int getWidth(int character, int size) {
201:
202: return getCharacterSet(size).width(character);
203:
204: }
205:
206: /**
207: * Get the getWidth (in 1/1000ths of a point size) of all characters in this
208: * character set.
209: *
210: * @param size
211: * the point size
212: * @return the widths of all characters
213: */
214: public int[] getWidths(int size) {
215:
216: return getCharacterSet(size).getWidths();
217:
218: }
219:
220: /**
221: * Get the getWidth (in 1/1000ths of a point size) of all characters in this
222: * character set.
223: *
224: * @return the widths of all characters
225: */
226: public int[] getWidths() {
227:
228: return getWidths(1000);
229:
230: }
231:
232: /**
233: * Map a Unicode character to a code point in the font.
234: * @param c character to map
235: * @return the mapped character
236: */
237: public char mapChar(char c) {
238: return _characterSet.mapChar(c);
239: }
240:
241: /**
242: * Get the encoding of the font.
243: * @return the encoding
244: */
245: public String getEncoding() {
246: return _characterSet.getEncoding();
247: }
248:
249: }
|