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$ */ 19 20 package org.apache.fop.fonts.type1; 21 22 import java.io.IOException; 23 import java.util.Map; 24 import java.util.Stack; 25 import java.util.regex.Matcher; 26 import java.util.regex.Pattern; 27 28 import org.apache.commons.logging.Log; 29 import org.apache.commons.logging.LogFactory; 30 31 import org.apache.xmlgraphics.fonts.Glyphs; 32 33 import org.apache.fop.fonts.NamedCharacter; 34 import org.apache.fop.fonts.type1.AFMParser.ValueHandler; 35 36 /** 37 * A handler that parses the various types of character metrics in an AFM file. 38 */ 39 abstract class CharMetricsHandler { 40 41 private static final Log LOG = LogFactory.getLog(CharMetricsHandler.class); 42 43 private static final String WHITE_SPACE = "\\s*"; 44 private static final String OPERATOR = "([A-Z0-9]{1,3})"; 45 private static final String OPERANDS = "(.*)"; 46 47 private static final Pattern METRICS_REGEX = Pattern.compile( 48 WHITE_SPACE + OPERATOR + WHITE_SPACE + OPERANDS + WHITE_SPACE); 49 private static final Pattern SPLIT_REGEX = Pattern.compile(WHITE_SPACE + ";" + WHITE_SPACE); 50 CharMetricsHandler()51 private CharMetricsHandler() { 52 } 53 parse(String line, Stack<Object> stack, String afmFileName)54 abstract AFMCharMetrics parse(String line, Stack<Object> stack, String afmFileName) 55 throws IOException; 56 getHandler(Map<String, ValueHandler> valueParsers, String line)57 static CharMetricsHandler getHandler(Map<String, ValueHandler> valueParsers, 58 String line) { 59 if (line != null && line.contains(AdobeStandardEncoding.NAME)) { 60 return new AdobeStandardCharMetricsHandler(valueParsers); 61 } else { 62 return new DefaultCharMetricsHandler(valueParsers); 63 } 64 } 65 66 private static final class DefaultCharMetricsHandler extends CharMetricsHandler { 67 private final Map<String, ValueHandler> valueParsers; 68 69 DefaultCharMetricsHandler(Map<String, ValueHandler> valueParsers)70 private DefaultCharMetricsHandler(Map<String, ValueHandler> valueParsers) { 71 this.valueParsers = valueParsers; 72 } 73 parse(String line, Stack<Object> stack, String afmFileName)74 AFMCharMetrics parse(String line, Stack<Object> stack, String afmFileName) 75 throws IOException { 76 AFMCharMetrics chm = new AFMCharMetrics(); 77 stack.push(chm); 78 String[] metrics = SPLIT_REGEX.split(line); 79 for (String metric : metrics) { 80 Matcher matcher = METRICS_REGEX.matcher(metric); 81 if (matcher.matches()) { 82 String operator = matcher.group(1); 83 String operands = matcher.group(2); 84 ValueHandler handler = valueParsers.get(operator); 85 if (handler != null) { 86 handler.parse(operands, 0, stack); 87 } 88 } 89 } 90 stack.pop(); 91 return chm; 92 } 93 } 94 95 private static final class AdobeStandardCharMetricsHandler extends CharMetricsHandler { 96 private final DefaultCharMetricsHandler defaultHandler; 97 AdobeStandardCharMetricsHandler(Map<String, ValueHandler> valueParsers)98 private AdobeStandardCharMetricsHandler(Map<String, ValueHandler> valueParsers) { 99 defaultHandler = new DefaultCharMetricsHandler(valueParsers); 100 } 101 parse(String line, Stack<Object> stack, String afmFileName)102 AFMCharMetrics parse(String line, Stack<Object> stack, String afmFileName) 103 throws IOException { 104 AFMCharMetrics chm = defaultHandler.parse(line, stack, afmFileName); 105 NamedCharacter namedChar = chm.getCharacter(); 106 if (namedChar != null) { 107 String charName = namedChar.getName(); 108 int codePoint = AdobeStandardEncoding.getAdobeCodePoint(charName); 109 if (chm.getCharCode() != codePoint && !Glyphs.NOTDEF.equals(charName)) { 110 LOG.info(afmFileName + ": named character '" + charName + "'" 111 + " has an incorrect code point: " + chm.getCharCode() 112 + ". Changed to " + codePoint); 113 chm.setCharCode(codePoint); 114 } 115 } 116 return chm; 117 } 118 } 119 120 } 121