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.complexscripts.fonts; 21 22 import java.util.Iterator; 23 import java.util.List; 24 25 import org.apache.commons.logging.Log; 26 import org.apache.commons.logging.LogFactory; 27 28 // CSOFF: LineLengthCheck 29 30 /** 31 * <p>Base class implementation of glyph class table.</p> 32 * 33 * <p>This work was originally authored by Glenn Adams (gadams@apache.org).</p> 34 */ 35 public final class GlyphClassTable extends GlyphMappingTable implements GlyphClassMapping { 36 37 /** empty mapping table */ 38 public static final int GLYPH_CLASS_TYPE_EMPTY = GLYPH_MAPPING_TYPE_EMPTY; 39 40 /** mapped mapping table */ 41 public static final int GLYPH_CLASS_TYPE_MAPPED = GLYPH_MAPPING_TYPE_MAPPED; 42 43 /** range based mapping table */ 44 public static final int GLYPH_CLASS_TYPE_RANGE = GLYPH_MAPPING_TYPE_RANGE; 45 46 /** empty mapping table */ 47 public static final int GLYPH_CLASS_TYPE_COVERAGE_SET = 3; 48 49 private GlyphClassMapping cm; 50 GlyphClassTable(GlyphClassMapping cm)51 private GlyphClassTable(GlyphClassMapping cm) { 52 assert cm != null; 53 assert cm instanceof GlyphMappingTable; 54 this.cm = cm; 55 } 56 57 /** {@inheritDoc} */ getType()58 public int getType() { 59 return ((GlyphMappingTable) cm) .getType(); 60 } 61 62 /** {@inheritDoc} */ getEntries()63 public List getEntries() { 64 return ((GlyphMappingTable) cm) .getEntries(); 65 } 66 67 /** {@inheritDoc} */ getClassSize(int set)68 public int getClassSize(int set) { 69 return cm.getClassSize(set); 70 } 71 72 /** {@inheritDoc} */ getClassIndex(int gid, int set)73 public int getClassIndex(int gid, int set) { 74 return cm.getClassIndex(gid, set); 75 } 76 77 /** 78 * Create glyph class table. 79 * @param entries list of mapped or ranged class entries, or null or empty list 80 * @return a new covera table instance 81 */ createClassTable(List entries)82 public static GlyphClassTable createClassTable(List entries) { 83 GlyphClassMapping cm; 84 if ((entries == null) || (entries.size() == 0)) { 85 cm = new EmptyClassTable(entries); 86 } else if (isMappedClass(entries)) { 87 cm = new MappedClassTable(entries); 88 } else if (isRangeClass(entries)) { 89 cm = new RangeClassTable(entries); 90 } else if (isCoverageSetClass(entries)) { 91 cm = new CoverageSetClassTable(entries); 92 } else { 93 cm = null; 94 } 95 assert cm != null : "unknown class type"; 96 return new GlyphClassTable(cm); 97 } 98 isMappedClass(List entries)99 private static boolean isMappedClass(List entries) { 100 if ((entries == null) || (entries.size() == 0)) { 101 return false; 102 } else { 103 for (Object o : entries) { 104 if (!(o instanceof Integer)) { 105 return false; 106 } 107 } 108 return true; 109 } 110 } 111 isRangeClass(List entries)112 private static boolean isRangeClass(List entries) { 113 if ((entries == null) || (entries.size() == 0)) { 114 return false; 115 } else { 116 for (Object o : entries) { 117 if (!(o instanceof MappingRange)) { 118 return false; 119 } 120 } 121 return true; 122 } 123 } 124 isCoverageSetClass(List entries)125 private static boolean isCoverageSetClass(List entries) { 126 if ((entries == null) || (entries.size() == 0)) { 127 return false; 128 } else { 129 for (Object o : entries) { 130 if (!(o instanceof GlyphCoverageTable)) { 131 return false; 132 } 133 } 134 return true; 135 } 136 } 137 138 private static class EmptyClassTable extends GlyphMappingTable.EmptyMappingTable implements GlyphClassMapping { EmptyClassTable(List entries)139 public EmptyClassTable(List entries) { 140 super(entries); 141 } 142 /** {@inheritDoc} */ getClassSize(int set)143 public int getClassSize(int set) { 144 return 0; 145 } 146 /** {@inheritDoc} */ getClassIndex(int gid, int set)147 public int getClassIndex(int gid, int set) { 148 return -1; 149 } 150 } 151 152 private static class MappedClassTable extends GlyphMappingTable.MappedMappingTable implements GlyphClassMapping { 153 private int firstGlyph; 154 private int[] gca; 155 private int gcMax = -1; MappedClassTable(List entries)156 public MappedClassTable(List entries) { 157 populate(entries); 158 } 159 /** {@inheritDoc} */ getEntries()160 public List getEntries() { 161 List entries = new java.util.ArrayList(); 162 entries.add(firstGlyph); 163 if (gca != null) { 164 for (int aGca : gca) { 165 entries.add(aGca); 166 } 167 } 168 return entries; 169 } 170 /** {@inheritDoc} */ getMappingSize()171 public int getMappingSize() { 172 return gcMax + 1; 173 } 174 /** {@inheritDoc} */ getMappedIndex(int gid)175 public int getMappedIndex(int gid) { 176 int i = gid - firstGlyph; 177 if ((i >= 0) && (i < gca.length)) { 178 return gca [ i ]; 179 } else { 180 return -1; 181 } 182 } 183 /** {@inheritDoc} */ getClassSize(int set)184 public int getClassSize(int set) { 185 return getMappingSize(); 186 } 187 /** {@inheritDoc} */ getClassIndex(int gid, int set)188 public int getClassIndex(int gid, int set) { 189 return getMappedIndex(gid); 190 } populate(List entries)191 private void populate(List entries) { 192 // obtain entries iterator 193 Iterator it = entries.iterator(); 194 // extract first glyph 195 int firstGlyph = 0; 196 if (it.hasNext()) { 197 Object o = it.next(); 198 if (o instanceof Integer) { 199 firstGlyph = (Integer) o; 200 } else { 201 throw new AdvancedTypographicTableFormatException("illegal entry, first entry must be Integer denoting first glyph value, but is: " + o); 202 } 203 } 204 // extract glyph class array 205 int i = 0; 206 int n = entries.size() - 1; 207 int gcMax = -1; 208 int[] gca = new int [ n ]; 209 while (it.hasNext()) { 210 Object o = it.next(); 211 if (o instanceof Integer) { 212 int gc = (Integer) o; 213 gca [ i++ ] = gc; 214 if (gc > gcMax) { 215 gcMax = gc; 216 } 217 } else { 218 throw new AdvancedTypographicTableFormatException("illegal mapping entry, must be Integer: " + o); 219 } 220 } 221 assert i == n; 222 assert this.gca == null; 223 this.firstGlyph = firstGlyph; 224 this.gca = gca; 225 this.gcMax = gcMax; 226 } 227 /** {@inheritDoc} */ toString()228 public String toString() { 229 StringBuffer sb = new StringBuffer(); 230 sb.append("{ firstGlyph = " + firstGlyph + ", classes = {"); 231 for (int i = 0, n = gca.length; i < n; i++) { 232 if (i > 0) { 233 sb.append(','); 234 } 235 sb.append(Integer.toString(gca [ i ])); 236 } 237 sb.append("} }"); 238 return sb.toString(); 239 } 240 } 241 242 private static class RangeClassTable extends GlyphMappingTable.RangeMappingTable implements GlyphClassMapping { RangeClassTable(List entries)243 public RangeClassTable(List entries) { 244 super(entries); 245 } 246 /** {@inheritDoc} */ getMappedIndex(int gid, int s, int m)247 public int getMappedIndex(int gid, int s, int m) { 248 return m; 249 } 250 /** {@inheritDoc} */ getClassSize(int set)251 public int getClassSize(int set) { 252 return getMappingSize(); 253 } 254 /** {@inheritDoc} */ getClassIndex(int gid, int set)255 public int getClassIndex(int gid, int set) { 256 return getMappedIndex(gid); 257 } 258 } 259 260 private static class CoverageSetClassTable extends GlyphMappingTable.EmptyMappingTable implements GlyphClassMapping { 261 private static final Log LOG = LogFactory.getLog(CoverageSetClassTable.class); CoverageSetClassTable(List entries)262 public CoverageSetClassTable(List entries) { 263 LOG.warn("coverage set class table not yet supported"); 264 } 265 /** {@inheritDoc} */ getType()266 public int getType() { 267 return GLYPH_CLASS_TYPE_COVERAGE_SET; 268 } 269 /** {@inheritDoc} */ getClassSize(int set)270 public int getClassSize(int set) { 271 return 0; 272 } 273 /** {@inheritDoc} */ getClassIndex(int gid, int set)274 public int getClassIndex(int gid, int set) { 275 return -1; 276 } 277 } 278 279 } 280