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: CustomFontMetricsMapper.java 1827168 2018-03-19 08:49:57Z ssteiner $ */ 19 20 package org.apache.fop.render.java2d; 21 22 import java.awt.Font; 23 import java.awt.FontFormatException; 24 import java.awt.Rectangle; 25 import java.io.IOException; 26 import java.io.InputStream; 27 import java.net.URI; 28 import java.util.List; 29 import java.util.Map; 30 import java.util.Set; 31 32 import org.apache.fop.complexscripts.fonts.Positionable; 33 import org.apache.fop.complexscripts.fonts.Substitutable; 34 import org.apache.fop.fonts.CustomFont; 35 import org.apache.fop.fonts.FontType; 36 import org.apache.fop.fonts.LazyFont; 37 import org.apache.fop.fonts.Typeface; 38 39 /** 40 * FontMetricsMapper that delegates most methods to an underlying 41 * {@link org.apache.fop.fonts.FontMetrics} instance. This class was designed to allow 42 * the underlying {@link Font} to be loaded from a 43 * user-configured file not registered in the current graphics environment. 44 */ 45 public class CustomFontMetricsMapper extends Typeface implements FontMetricsMapper, Substitutable, 46 Positionable { 47 48 /** 49 * Font metrics for the font this class models. 50 */ 51 private Typeface typeface; 52 53 /** 54 * The font required by the Java2D renderer. 55 */ 56 private java.awt.Font font; 57 58 /** 59 * Maintains the most recently requested size. 60 */ 61 private float size = 1; 62 63 /** 64 * Construction of this class results in the immediate construction 65 * of the underlying {@link java.awt.Font}. 66 * @param fontMetrics the metrics of the custom font 67 * @throws FontFormatException if a bad font is loaded 68 * @throws IOException if an I/O error occurs 69 */ CustomFontMetricsMapper(final CustomFont fontMetrics)70 public CustomFontMetricsMapper(final CustomFont fontMetrics) 71 throws FontFormatException, IOException { 72 this.typeface = fontMetrics; 73 initialize(fontMetrics.getInputStream()); 74 } 75 76 /** 77 * Construction of this class results in the immediate construction 78 * of the underlying {@link java.awt.Font}. 79 * @param fontMetrics the font 80 * @param fontSource the font source to access the font 81 * @throws FontFormatException if a bad font is loaded 82 * @throws IOException if an I/O error occurs 83 */ CustomFontMetricsMapper(final LazyFont fontMetrics, final InputStream fontSource)84 public CustomFontMetricsMapper(final LazyFont fontMetrics, final InputStream fontSource) 85 throws FontFormatException, IOException { 86 this.typeface = fontMetrics; 87 initialize(fontSource); 88 } 89 90 private static final int TYPE1_FONT = 1; //Defined in Java 1.5 91 92 /** 93 * Loads the java.awt.Font 94 * @param inStream 95 * @throws FontFormatException 96 * @throws IOException 97 */ initialize(final InputStream inStream)98 private void initialize(final InputStream inStream) 99 throws FontFormatException, IOException { 100 int type = Font.TRUETYPE_FONT; 101 if (FontType.TYPE1.equals(typeface.getFontType())) { 102 type = TYPE1_FONT; //Font.TYPE1_FONT; only available in Java 1.5 103 } 104 this.font = Font.createFont(type, inStream); 105 inStream.close(); 106 } 107 108 /** {@inheritDoc} */ getEncodingName()109 public final String getEncodingName() { 110 return null; //Not applicable to Java2D rendering 111 } 112 113 /** {@inheritDoc} */ hasChar(final char c)114 public final boolean hasChar(final char c) { 115 return font.canDisplay(c); 116 } 117 118 /** {@inheritDoc} */ mapChar(final char c)119 public final char mapChar(final char c) { 120 return typeface.mapChar(c); 121 } 122 123 /** {@inheritDoc} */ getFont(final int size)124 public final Font getFont(final int size) { 125 if (this.size == size) { 126 return font; 127 } 128 129 this.size = size / 1000f; 130 font = font.deriveFont(this.size); 131 return font; 132 } 133 134 /** {@inheritDoc} */ getAscender(final int size)135 public final int getAscender(final int size) { 136 return typeface.getAscender(size); 137 } 138 139 /** {@inheritDoc} */ getCapHeight(final int size)140 public final int getCapHeight(final int size) { 141 return typeface.getCapHeight(size); 142 } 143 144 /** {@inheritDoc} */ getDescender(final int size)145 public final int getDescender(final int size) { 146 return typeface.getDescender(size); 147 } 148 149 /** {@inheritDoc} */ getEmbedFontName()150 public final String getEmbedFontName() { 151 return typeface.getEmbedFontName(); 152 } 153 154 /** {@inheritDoc} */ getFamilyNames()155 public final Set<String> getFamilyNames() { 156 return typeface.getFamilyNames(); 157 } 158 159 /** {@inheritDoc} */ getFontName()160 public final String getFontName() { 161 return typeface.getFontName(); 162 } 163 164 /** {@inheritDoc} */ getFontURI()165 public final URI getFontURI() { 166 return typeface.getFontURI(); 167 } 168 169 /** {@inheritDoc} */ getFontType()170 public final FontType getFontType() { 171 return typeface.getFontType(); 172 } 173 174 /** {@inheritDoc} */ getFullName()175 public final String getFullName() { 176 return typeface.getFullName(); 177 } 178 179 /** {@inheritDoc} */ getKerningInfo()180 public final Map getKerningInfo() { 181 return typeface.getKerningInfo(); 182 } 183 184 /** {@inheritDoc} */ getWidth(final int i, final int size)185 public final int getWidth(final int i, final int size) { 186 return typeface.getWidth(i, size); 187 } 188 189 /** {@inheritDoc} */ getWidths()190 public final int[] getWidths() { 191 return typeface.getWidths(); 192 } 193 getBoundingBox(int glyphIndex, int size)194 public Rectangle getBoundingBox(int glyphIndex, int size) { 195 return typeface.getBoundingBox(glyphIndex, size); 196 } 197 198 /** {@inheritDoc} */ getXHeight(final int size)199 public final int getXHeight(final int size) { 200 return typeface.getXHeight(size); 201 } 202 getUnderlinePosition(int size)203 public int getUnderlinePosition(int size) { 204 return typeface.getUnderlinePosition(size); 205 } 206 getUnderlineThickness(int size)207 public int getUnderlineThickness(int size) { 208 return typeface.getUnderlineThickness(size); 209 } 210 getStrikeoutPosition(int size)211 public int getStrikeoutPosition(int size) { 212 return typeface.getStrikeoutPosition(size); 213 } 214 getStrikeoutThickness(int size)215 public int getStrikeoutThickness(int size) { 216 return typeface.getStrikeoutThickness(size); 217 } 218 219 /** {@inheritDoc} */ hasKerningInfo()220 public final boolean hasKerningInfo() { 221 return typeface.hasKerningInfo(); 222 } 223 224 /** {@inheritDoc} */ isMultiByte()225 public boolean isMultiByte() { 226 return typeface.isMultiByte(); 227 } 228 229 /** 230 * {@inheritDoc} 231 */ performsPositioning()232 public boolean performsPositioning() { 233 if (typeface instanceof Positionable) { 234 return ((Positionable) typeface).performsPositioning(); 235 } else { 236 return false; 237 } 238 } 239 240 /** 241 * {@inheritDoc} 242 */ performPositioning(CharSequence cs, String script, String language, int fontSize)243 public int[][] performPositioning(CharSequence cs, String script, String language, int fontSize) { 244 if (typeface instanceof Positionable) { 245 return ((Positionable) typeface).performPositioning(cs, script, language, fontSize); 246 } else { 247 return null; 248 } 249 } 250 251 /** 252 * {@inheritDoc} 253 */ performPositioning(CharSequence cs, String script, String language)254 public int[][] performPositioning(CharSequence cs, String script, String language) { 255 if (typeface instanceof Positionable) { 256 return ((Positionable) typeface).performPositioning(cs, script, language); 257 } else { 258 return null; 259 } 260 } 261 262 /** 263 * {@inheritDoc} 264 */ performsSubstitution()265 public boolean performsSubstitution() { 266 if (typeface instanceof Substitutable) { 267 return ((Substitutable) typeface).performsSubstitution(); 268 } else { 269 return false; 270 } 271 } 272 273 /** 274 * {@inheritDoc} 275 */ performSubstitution(CharSequence cs, String script, String language, List associations, boolean retainControls)276 public CharSequence performSubstitution(CharSequence cs, String script, String language, List associations, 277 boolean retainControls) { 278 if (typeface instanceof Substitutable) { 279 return ((Substitutable) typeface).performSubstitution(cs, script, language, associations, retainControls); 280 } else { 281 return cs; 282 } 283 } 284 285 /** 286 * {@inheritDoc} 287 */ reorderCombiningMarks(CharSequence cs, int[][] gpa, String script, String language, List associations)288 public CharSequence reorderCombiningMarks(CharSequence cs, int[][] gpa, 289 String script, String language, List associations) { 290 if (typeface instanceof Substitutable) { 291 return ((Substitutable) typeface).reorderCombiningMarks(cs, gpa, script, language, associations); 292 } else { 293 return cs; 294 } 295 } 296 getRealFont()297 public Typeface getRealFont() { 298 return typeface; 299 } 300 301 } 302