1 /* 2 * Licensed to the Apache Software Foundation (ASF) under one or more 3 * contributor license agreements. See the NOTICE file distributed with 4 * this work for additional information regarding copyright ownership. 5 * The ASF licenses this file to You under the Apache License, Version 2.0 6 * (the "License"); you may not use this file except in compliance with 7 * the License. You may obtain a copy of the License at 8 * 9 * http://www.apache.org/licenses/LICENSE-2.0 10 * 11 * Unless required by applicable law or agreed to in writing, software 12 * distributed under the License is distributed on an "AS IS" BASIS, 13 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 14 * See the License for the specific language governing permissions and 15 * limitations under the License. 16 */ 17 18 /* $Id: Typeface.java 1792597 2017-04-25 10:18:07Z ssteiner $ */ 19 20 package org.apache.fop.fonts; 21 22 import java.util.HashSet; 23 import java.util.Set; 24 25 import org.apache.commons.logging.Log; 26 import org.apache.commons.logging.LogFactory; 27 28 import org.apache.xmlgraphics.fonts.Glyphs; 29 30 /** 31 * Base class for font classes 32 */ 33 public abstract class Typeface implements FontMetrics { 34 35 /** 36 * Code point that is used if no code point for a specific character has 37 * been found. 38 */ 39 public static final char NOT_FOUND = '#'; 40 41 /** logger */ 42 private static Log log = LogFactory.getLog(Typeface.class); 43 44 /** 45 * Used to identify whether a font has been used (a character map operation 46 * is used as the trigger). This could just as well be a boolean but is a 47 * long out of statistical interest. 48 */ 49 private long charMapOps; 50 51 /** An optional event listener that receives events such as missing glyphs etc. */ 52 protected FontEventListener eventListener; 53 54 private Set<Character> warnedChars; 55 56 /** 57 * Get the encoding of the font. 58 * @return the encoding 59 */ getEncodingName()60 public abstract String getEncodingName(); 61 62 /** 63 * Map a Unicode character to a code point in the font. 64 * @param c character to map 65 * @return the mapped character 66 */ mapChar(char c)67 public abstract char mapChar(char c); 68 69 /** 70 * Used for keeping track of character mapping operations in order to determine if a font 71 * was used at all or not. 72 */ notifyMapOperation()73 protected void notifyMapOperation() { 74 this.charMapOps++; 75 } 76 77 /** 78 * Indicates whether this font had to do any character mapping operations. If that was 79 * not the case, it's an indication that the font has never actually been used. 80 * @return true if the font had to do any character mapping operations 81 */ hadMappingOperations()82 public boolean hadMappingOperations() { 83 return (this.charMapOps > 0); 84 } 85 86 /** 87 * Determines whether this font contains a particular character/glyph. 88 * @param c character to check 89 * @return True if the character is supported, Falso otherwise 90 */ hasChar(char c)91 public abstract boolean hasChar(char c); 92 93 /** 94 * Determines whether the font is a multibyte font. 95 * @return True if it is multibyte 96 */ isMultiByte()97 public boolean isMultiByte() { 98 return false; 99 } 100 isCID()101 public boolean isCID() { 102 return getFontType() == FontType.TYPE1C; 103 } 104 105 /** {@inheritDoc} */ getMaxAscent(int size)106 public int getMaxAscent(int size) { 107 return getAscender(size); 108 } 109 110 /** {@inheritDoc} */ hasFeature(int tableType, String script, String language, String feature)111 public boolean hasFeature(int tableType, String script, String language, String feature) { 112 return false; 113 } 114 115 /** 116 * Sets the font event listener that can be used to receive events about particular events 117 * in this class. 118 * @param listener the font event listener 119 */ setEventListener(FontEventListener listener)120 public void setEventListener(FontEventListener listener) { 121 this.eventListener = listener; 122 } 123 124 /** 125 * Provide proper warning if a glyph is not available. 126 * 127 * @param c 128 * the character which is missing. 129 */ warnMissingGlyph(char c)130 protected void warnMissingGlyph(char c) { 131 // Give up, character is not available 132 Character ch = c; 133 if (warnedChars == null) { 134 warnedChars = new HashSet<Character>(); 135 } 136 if (warnedChars.size() < 8 && !warnedChars.contains(ch)) { 137 warnedChars.add(ch); 138 if (this.eventListener != null) { 139 this.eventListener.glyphNotAvailable(this, c, getFontName()); 140 } else { 141 if (warnedChars.size() == 8) { 142 log.warn("Many requested glyphs are not available in font " 143 + getFontName()); 144 } else { 145 log.warn("Glyph " + (int) c + " (0x" 146 + Integer.toHexString(c) + ", " 147 + Glyphs.charToGlyphName(c) 148 + ") not available in font " + getFontName()); 149 } 150 } 151 } 152 } 153 154 /** {@inheritDoc} */ toString()155 public String toString() { 156 StringBuffer sbuf = new StringBuffer(super.toString()); 157 sbuf.append('{'); 158 sbuf.append(getFullName()); 159 sbuf.append('}'); 160 return sbuf.toString(); 161 } 162 } 163