Vous ne pouvez pas sélectionner plus de 25 sujets Les noms de sujets doivent commencer par une lettre ou un nombre, peuvent contenir des tirets ('-') et peuvent comporter jusqu'à 35 caractères.

AbstractCodePointMapping.java 7.1KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216
  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.fonts;
  19. import java.util.Arrays;
  20. import org.apache.xmlgraphics.fonts.Glyphs;
  21. import org.apache.fop.util.CharUtilities;
  22. /**
  23. * Abstract base class for code point mapping classes (1-byte character encodings).
  24. */
  25. public class AbstractCodePointMapping implements SingleByteEncoding {
  26. private final String name;
  27. private char[] latin1Map;
  28. private char[] characters;
  29. private char[] codepoints;
  30. private char[] unicodeMap; //code point to Unicode char
  31. private String[] charNameMap; //all character names in the encoding
  32. /**
  33. * Main constructor.
  34. * @param name the name of the encoding
  35. * @param table the table ([code point, unicode scalar value]+) with the mapping
  36. */
  37. public AbstractCodePointMapping(String name, int[] table) {
  38. this(name, table, null);
  39. }
  40. /**
  41. * Extended constructor.
  42. * @param name the name of the encoding
  43. * @param table the table ([code point, unicode scalar value]+) with the mapping
  44. * @param charNameMap all character names in the encoding (a value of null will be converted
  45. * to ".notdef")
  46. */
  47. public AbstractCodePointMapping(String name, int[] table, String[] charNameMap) {
  48. this.name = name;
  49. buildFromTable(table);
  50. if (charNameMap != null) {
  51. this.charNameMap = new String[256];
  52. for (int i = 0; i < 256; i++) {
  53. String charName = charNameMap[i];
  54. if (charName == null) {
  55. this.charNameMap[i] = Glyphs.NOTDEF;
  56. } else {
  57. this.charNameMap[i] = charName;
  58. }
  59. }
  60. }
  61. }
  62. /**
  63. * Builds the internal lookup structures based on a given table.
  64. * @param table the table ([code point, unicode scalar value]+) with the mapping
  65. */
  66. protected void buildFromTable(int[] table) {
  67. int nonLatin1 = 0;
  68. latin1Map = new char[256];
  69. unicodeMap = new char[256];
  70. Arrays.fill(unicodeMap, CharUtilities.NOT_A_CHARACTER);
  71. for (int i = 0; i < table.length; i += 2) {
  72. char unicode = (char)table[i + 1];
  73. if (unicode < 256) {
  74. if (latin1Map[unicode] == 0) {
  75. latin1Map[unicode] = (char) table[i];
  76. }
  77. } else {
  78. ++nonLatin1;
  79. }
  80. if (unicodeMap[table[i]] == CharUtilities.NOT_A_CHARACTER) {
  81. unicodeMap[table[i]] = unicode;
  82. }
  83. }
  84. characters = new char[nonLatin1];
  85. codepoints = new char[nonLatin1];
  86. int top = 0;
  87. for (int i = 0; i < table.length; i += 2) {
  88. char c = (char) table[i + 1];
  89. if (c >= 256) {
  90. ++top;
  91. for (int j = top - 1; j >= 0; --j) {
  92. if (j > 0 && characters[j - 1] >= c) {
  93. characters[j] = characters[j - 1];
  94. codepoints[j] = codepoints[j - 1];
  95. } else {
  96. characters[j] = c;
  97. codepoints[j] = (char) table[i];
  98. break;
  99. }
  100. }
  101. }
  102. }
  103. }
  104. /** {@inheritDoc} */
  105. public String getName() {
  106. return this.name;
  107. }
  108. /** {@inheritDoc} */
  109. public final char mapChar(char c) {
  110. if (c < 256) {
  111. char latin1 = latin1Map[c];
  112. if (latin1 > 0) {
  113. return latin1;
  114. }
  115. }
  116. int bot = 0;
  117. int top = characters.length - 1;
  118. while (top >= bot) {
  119. assert bot < 65536;
  120. assert top < 65536;
  121. int mid = (bot + top) >>> 1;
  122. char mc = characters[mid];
  123. if (c == mc) {
  124. return codepoints[mid];
  125. } else if (c < mc) {
  126. top = mid - 1;
  127. } else {
  128. bot = mid + 1;
  129. }
  130. }
  131. return NOT_FOUND_CODE_POINT;
  132. }
  133. /**
  134. * Returns the main Unicode value that is associated with the given code point in the encoding.
  135. * Note that multiple Unicode values can theoretically be mapped to one code point in the
  136. * encoding.
  137. * @param idx the code point in the encoding
  138. * @return the Unicode value (or \uFFFF (NOT A CHARACTER) if no Unicode value is at that point)
  139. */
  140. public final char getUnicodeForIndex(int idx) {
  141. return this.unicodeMap[idx];
  142. }
  143. /** {@inheritDoc} */
  144. public final char[] getUnicodeCharMap() {
  145. char[] copy = new char[this.unicodeMap.length];
  146. System.arraycopy(this.unicodeMap, 0, copy, 0, this.unicodeMap.length);
  147. return copy;
  148. }
  149. /**
  150. * Returns the index of a character/glyph with the given name. Note that this
  151. * method is relatively slow and should only be used for fallback operations.
  152. * @param charName the character name
  153. * @return the index of the character in the encoding or -1 if it doesn't exist
  154. */
  155. public short getCodePointForGlyph(String charName) {
  156. String[] names = this.charNameMap;
  157. if (names == null) {
  158. names = getCharNameMap();
  159. }
  160. for (short i = 0, c = (short)names.length; i < c; i++) {
  161. if (names[i].equals(charName)) {
  162. return i;
  163. }
  164. }
  165. return -1;
  166. }
  167. public String getNameFromCodePoint(int idx) {
  168. return getCharNameMap()[idx];
  169. }
  170. /** {@inheritDoc} */
  171. public String[] getCharNameMap() {
  172. if (this.charNameMap != null) {
  173. String[] copy = new String[this.charNameMap.length];
  174. System.arraycopy(this.charNameMap, 0, copy, 0, this.charNameMap.length);
  175. return copy;
  176. } else {
  177. //Note: this is suboptimal but will probably never be used.
  178. String[] derived = new String[256];
  179. Arrays.fill(derived, Glyphs.NOTDEF);
  180. for (int i = 0; i < 256; i++) {
  181. char c = getUnicodeForIndex(i);
  182. if (c != CharUtilities.NOT_A_CHARACTER) {
  183. String charName = Glyphs.charToGlyphName(c);
  184. if (charName.length() > 0) {
  185. derived[i] = charName;
  186. }
  187. }
  188. }
  189. return derived;
  190. }
  191. }
  192. /** {@inheritDoc} */
  193. @Override
  194. public String toString() {
  195. return getName();
  196. }
  197. }