123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284 |
- /*
- * 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.
- */
-
- /* $Id$ */
-
- package org.apache.fop.afp.fonts;
-
- import java.util.HashMap;
- import java.util.Iterator;
- import java.util.Map;
- import java.util.SortedMap;
- import java.util.TreeMap;
-
- import org.apache.commons.logging.Log;
- import org.apache.commons.logging.LogFactory;
-
- /**
- * A font where each character is stored as an array of pixels (a bitmap). Such
- * fonts are not easily scalable, in contrast to vectored fonts. With this type
- * of font, the font metrics information is held in character set files (one for
- * each size and style). <p/>
- *
- */
- public class RasterFont extends AFPFont {
-
- /** Static logging instance */
- protected static final Log LOG = LogFactory.getLog("org.apache.fop.afp.fonts");
-
- private final SortedMap<Integer, CharacterSet> charSets = new TreeMap<Integer, CharacterSet>();
- private Map<Integer, CharacterSet> substitutionCharSets;
-
- private CharacterSet charSet = null;
-
- /**
- * Constructor for the raster font requires the name, weight and style
- * attribute to be available as this forms the key to the font.
- *
- * @param name
- * the name of the font
- */
- public RasterFont(String name, boolean embeddable) {
- super(name, embeddable);
- }
-
- /**
- * Adds the character set for the given point size
- * @param size point size (in mpt)
- * @param characterSet character set
- */
- public void addCharacterSet(int size, CharacterSet characterSet) {
- //TODO: replace with Integer.valueOf() once we switch to Java 5
- this.charSets.put(new Integer(size), characterSet);
- this.charSet = characterSet;
- }
-
- /**
- * Get the character set metrics for the specified point size.
- *
- * @param sizeInMpt the point size (in mpt)
- * @return the character set metrics
- */
- public CharacterSet getCharacterSet(int sizeInMpt) {
-
- Integer requestedSize = Integer.valueOf(sizeInMpt);
- CharacterSet csm = charSets.get(requestedSize);
- double sizeInPt = sizeInMpt / 1000.0;
-
- if (csm != null) {
- return csm;
- }
-
- if (substitutionCharSets != null) {
- //Check first if a substitution has already been added
- csm = substitutionCharSets.get(requestedSize);
- }
-
- if (csm == null && !charSets.isEmpty()) {
- // No match or substitution found, but there exist entries
- // for other sizes
- // Get char set with nearest, smallest font size
- SortedMap<Integer, CharacterSet> smallerSizes = charSets.headMap(requestedSize);
- SortedMap<Integer, CharacterSet> largerSizes = charSets.tailMap(requestedSize);
- int smallerSize = smallerSizes.isEmpty() ? 0
- : smallerSizes.lastKey().intValue();
- int largerSize = largerSizes.isEmpty() ? Integer.MAX_VALUE
- : largerSizes.firstKey().intValue();
-
- Integer fontSize;
- if (!smallerSizes.isEmpty()
- && (sizeInMpt - smallerSize) <= (largerSize - sizeInMpt)) {
- fontSize = Integer.valueOf(smallerSize);
- } else {
- fontSize = Integer.valueOf(largerSize);
- }
- csm = charSets.get(fontSize);
-
- if (csm != null) {
- // Add the substitute mapping, so subsequent calls will
- // find it immediately
- if (substitutionCharSets == null) {
- substitutionCharSets = new HashMap<Integer, CharacterSet>();
- }
- substitutionCharSets.put(requestedSize, csm);
- // do not output the warning if the font size is closer to an integer less than 0.1
- if (!(Math.abs(fontSize.intValue() / 1000.0 - sizeInPt) < 0.1)) {
- String msg = "No " + sizeInPt + "pt font " + getFontName()
- + " found, substituted with " + fontSize.intValue() / 1000f + "pt font";
- LOG.warn(msg);
- }
- }
- }
-
- if (csm == null) {
- // Still no match -> error
- String msg = "No font found for font " + getFontName() + " with point size " + sizeInPt;
- LOG.error(msg);
- throw new FontRuntimeException(msg);
- }
-
- return csm;
-
- }
-
- /**
- * Get the first character in this font.
- * @return the first character in this font.
- */
- public int getFirstChar() {
- Iterator<CharacterSet> it = charSets.values().iterator();
- if (it.hasNext()) {
- CharacterSet csm = it.next();
- return csm.getFirstChar();
- } else {
- String msg = "getFirstChar() - No character set found for font:" + getFontName();
- LOG.error(msg);
- throw new FontRuntimeException(msg);
- }
- }
-
- /**
- * Get the last character in this font.
- * @return the last character in this font.
- */
- public int getLastChar() {
-
- Iterator<CharacterSet> it = charSets.values().iterator();
- if (it.hasNext()) {
- CharacterSet csm = it.next();
- return csm.getLastChar();
- } else {
- String msg = "getLastChar() - No character set found for font:" + getFontName();
- LOG.error(msg);
- throw new FontRuntimeException(msg);
- }
-
- }
-
- private int metricsToAbsoluteSize(CharacterSet cs, int value, int givenSize) {
- int nominalVerticalSize = cs.getNominalVerticalSize();
- if (nominalVerticalSize != 0) {
- return value * nominalVerticalSize;
- } else {
- return value * givenSize;
- }
- }
-
- /**
- * The ascender is the part of a lowercase letter that extends above the
- * "x-height" (the height of the letter "x"), such as "d", "t", or "h". Also
- * used to denote the part of the letter extending above the x-height.
- *
- * @param size the font size (in mpt)
- * @return the ascender for the given point size
- */
- public int getAscender(int size) {
- CharacterSet cs = getCharacterSet(size);
- return metricsToAbsoluteSize(cs, cs.getAscender(), size);
- }
-
- /**
- * Obtains the height of capital letters for the specified point size.
- *
- * @param size the font size (in mpt)
- * @return the cap height for the specified point size
- */
- public int getCapHeight(int size) {
- CharacterSet cs = getCharacterSet(size);
- return metricsToAbsoluteSize(cs, cs.getCapHeight(), size);
- }
-
- /**
- * The descender is the part of a lowercase letter that extends below the
- * base line, such as "g", "j", or "p". Also used to denote the part of the
- * letter extending below the base line.
- *
- * @param size the font size (in mpt)
- * @return the descender for the specified point size
- */
- public int getDescender(int size) {
- CharacterSet cs = getCharacterSet(size);
- return metricsToAbsoluteSize(cs, cs.getDescender(), size);
- }
-
- /**
- * The "x-height" (the height of the letter "x").
- *
- * @param size the font size (in mpt)
- * @return the x height for the given point size
- */
- public int getXHeight(int size) {
- CharacterSet cs = getCharacterSet(size);
- return metricsToAbsoluteSize(cs, cs.getXHeight(), size);
- }
-
- /**
- * Obtain the width of the character for the specified point size.
- * @param character the character
- * @param size the font size (in mpt)
- * @return the width for the given point size
- */
- public int getWidth(int character, int size) {
- CharacterSet cs = getCharacterSet(size);
- return metricsToAbsoluteSize(cs, cs.getWidth(toUnicodeCodepoint(character)), size);
- }
-
- /**
- * Get the getWidth (in 1/1000ths of a point size) of all characters in this
- * character set.
- *
- * @param size the font size (in mpt)
- * @return the widths of all characters
- */
- public int[] getWidths(int size) {
- CharacterSet cs = getCharacterSet(size);
- int[] widths = cs.getWidths();
- for (int i = 0, c = widths.length; i < c; i++) {
- widths[i] = metricsToAbsoluteSize(cs, widths[i], size);
- }
- return widths;
- }
-
- /**
- * Get the getWidth (in 1/1000ths of a point size) of all characters in this
- * character set.
- *
- * @return the widths of all characters
- */
- public int[] getWidths() {
- return getWidths(1000);
- }
-
- /** {@inheritDoc} */
- public boolean hasChar(char c) {
- return charSet.hasChar(c);
- }
-
- /**
- * Map a Unicode character to a code point in the font.
- * @param c character to map
- * @return the mapped character
- */
- public char mapChar(char c) {
- return charSet.mapChar(c);
- }
-
- /** {@inheritDoc} */
- public String getEncodingName() {
- return charSet.getEncoding();
- }
- }
|