You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

GlyphClassTable.java 8.9KB

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