選択できるのは25トピックまでです。 トピックは、先頭が英数字で、英数字とダッシュ('-')を使用した35文字以内のものにしてください。

SingleByteFont.java 9.7KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298
  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.List;
  20. import java.util.Map;
  21. import org.apache.commons.logging.Log;
  22. import org.apache.commons.logging.LogFactory;
  23. /**
  24. * Generic SingleByte font
  25. */
  26. public class SingleByteFont extends CustomFont {
  27. /** logger */
  28. private static Log log = LogFactory.getLog(SingleByteFont.class);
  29. private SingleByteEncoding mapping;
  30. private int[] width = null;
  31. private Map unencodedCharacters;
  32. //Map<Character, UnencodedCharacter>
  33. private List additionalEncodings;
  34. /**
  35. * Main constructor.
  36. */
  37. public SingleByteFont() {
  38. setEncoding(CodePointMapping.WIN_ANSI_ENCODING);
  39. }
  40. /** {@inheritDoc} */
  41. public boolean isEmbeddable() {
  42. return (!(getEmbedFileName() == null
  43. && getEmbedResourceName() == null));
  44. }
  45. /** {@inheritDoc} */
  46. public String getEncodingName() {
  47. return this.mapping.getName();
  48. }
  49. /**
  50. * Returns the code point mapping (encoding) of this font.
  51. * @return the code point mapping
  52. */
  53. public SingleByteEncoding getEncoding() {
  54. return this.mapping;
  55. }
  56. /** {@inheritDoc} */
  57. public int getWidth(int i, int size) {
  58. if (i < 256) {
  59. int idx = i - getFirstChar();
  60. if (idx >= 0 && idx < width.length) {
  61. return size * width[i - getFirstChar()];
  62. }
  63. } else if (this.additionalEncodings != null) {
  64. int encodingIndex = (i / 256) - 1;
  65. SimpleSingleByteEncoding encoding = getAdditionalEncoding(encodingIndex);
  66. int codePoint = i % 256;
  67. NamedCharacter nc = encoding.getCharacterForIndex(codePoint);
  68. UnencodedCharacter uc
  69. = (UnencodedCharacter)this.unencodedCharacters.get(
  70. new Character(nc.getSingleUnicodeValue()));
  71. return size * uc.getWidth();
  72. }
  73. return 0;
  74. }
  75. /** {@inheritDoc} */
  76. public int[] getWidths() {
  77. int[] arr = new int[width.length];
  78. System.arraycopy(width, 0, arr, 0, width.length - 1);
  79. return arr;
  80. }
  81. /** {@inheritDoc} */
  82. public char mapChar(char c) {
  83. notifyMapOperation();
  84. char d = mapping.mapChar(c);
  85. if (d != SingleByteEncoding.NOT_FOUND_CODE_POINT) {
  86. return d;
  87. }
  88. //Check unencoded characters which are available in the font by character name
  89. d = mapUnencodedChar(c);
  90. if (d != SingleByteEncoding.NOT_FOUND_CODE_POINT) {
  91. return d;
  92. }
  93. this.warnMissingGlyph(c);
  94. return Typeface.NOT_FOUND;
  95. }
  96. private char mapUnencodedChar(char ch) {
  97. if (this.unencodedCharacters != null) {
  98. UnencodedCharacter unencoded
  99. = (UnencodedCharacter)this.unencodedCharacters.get(new Character(ch));
  100. if (unencoded != null) {
  101. if (this.additionalEncodings == null) {
  102. this.additionalEncodings = new java.util.ArrayList();
  103. }
  104. SimpleSingleByteEncoding encoding = null;
  105. char mappedStart = 0;
  106. int additionalsCount = this.additionalEncodings.size();
  107. for (int i = 0; i < additionalsCount; i++) {
  108. mappedStart += 256;
  109. encoding = getAdditionalEncoding(i);
  110. char alt = encoding.mapChar(ch);
  111. if (alt != 0) {
  112. return (char)(mappedStart + alt);
  113. }
  114. }
  115. if (encoding != null && encoding.isFull()) {
  116. encoding = null;
  117. }
  118. if (encoding == null) {
  119. encoding = new SimpleSingleByteEncoding(
  120. getFontName() + "EncodingSupp" + (additionalsCount + 1));
  121. this.additionalEncodings.add(encoding);
  122. mappedStart += 256;
  123. }
  124. return (char)(mappedStart + encoding.addCharacter(unencoded.getCharacter()));
  125. }
  126. }
  127. return 0;
  128. }
  129. /** {@inheritDoc} */
  130. public boolean hasChar(char c) {
  131. char d = mapping.mapChar(c);
  132. if (d != SingleByteEncoding.NOT_FOUND_CODE_POINT) {
  133. return true;
  134. }
  135. //Check unencoded characters which are available in the font by character name
  136. d = mapUnencodedChar(c);
  137. if (d != SingleByteEncoding.NOT_FOUND_CODE_POINT) {
  138. return true;
  139. }
  140. return false;
  141. }
  142. /* ---- single byte font specific setters --- */
  143. /**
  144. * Updates the mapping variable based on the encoding.
  145. * @param encoding the name of the encoding
  146. */
  147. protected void updateMapping(String encoding) {
  148. try {
  149. this.mapping = CodePointMapping.getMapping(encoding);
  150. } catch (UnsupportedOperationException e) {
  151. log.error("Font '" + super.getFontName() + "': " + e.getMessage());
  152. }
  153. }
  154. /**
  155. * Sets the encoding of the font.
  156. * @param encoding the encoding (ex. "WinAnsiEncoding" or "SymbolEncoding")
  157. */
  158. public void setEncoding(String encoding) {
  159. updateMapping(encoding);
  160. }
  161. /**
  162. * Sets the encoding of the font.
  163. * @param encoding the encoding information
  164. */
  165. public void setEncoding(CodePointMapping encoding) {
  166. this.mapping = encoding;
  167. }
  168. /**
  169. * Sets a width for a character.
  170. * @param index index of the character
  171. * @param w the width of the character
  172. */
  173. public void setWidth(int index, int w) {
  174. if (this.width == null) {
  175. this.width = new int[getLastChar() - getFirstChar() + 1];
  176. }
  177. this.width[index - getFirstChar()] = w;
  178. }
  179. /**
  180. * Adds an unencoded character (one that is not supported by the primary encoding).
  181. * @param ch the named character
  182. * @param width the width of the character
  183. */
  184. public void addUnencodedCharacter(NamedCharacter ch, int width) {
  185. if (this.unencodedCharacters == null) {
  186. this.unencodedCharacters = new java.util.HashMap();
  187. }
  188. if (ch.hasSingleUnicodeValue()) {
  189. UnencodedCharacter uc = new UnencodedCharacter(ch, width);
  190. this.unencodedCharacters.put(new Character(ch.getSingleUnicodeValue()), uc);
  191. } else {
  192. //Cannot deal with unicode sequences, so ignore this character
  193. }
  194. }
  195. /**
  196. * Indicates whether the encoding has additional encodings besides the primary encoding.
  197. * @return true if there are additional encodings.
  198. */
  199. public boolean hasAdditionalEncodings() {
  200. return (this.additionalEncodings != null) && (this.additionalEncodings.size() > 0);
  201. }
  202. /**
  203. * Returns the number of additional encodings this single-byte font maintains.
  204. * @return the number of additional encodings
  205. */
  206. public int getAdditionalEncodingCount() {
  207. if (hasAdditionalEncodings()) {
  208. return this.additionalEncodings.size();
  209. } else {
  210. return 0;
  211. }
  212. }
  213. /**
  214. * Returns an additional encoding.
  215. * @param index the index of the additional encoding
  216. * @return the additional encoding
  217. * @throws IndexOutOfBoundsException if the index is out of bounds
  218. */
  219. public SimpleSingleByteEncoding getAdditionalEncoding(int index)
  220. throws IndexOutOfBoundsException {
  221. if (hasAdditionalEncodings()) {
  222. return (SimpleSingleByteEncoding)this.additionalEncodings.get(index);
  223. } else {
  224. throw new IndexOutOfBoundsException("No additional encodings available");
  225. }
  226. }
  227. /**
  228. * Returns an array with the widths for an additional encoding.
  229. * @param index the index of the additional encoding
  230. * @return the width array
  231. */
  232. public int[] getAdditionalWidths(int index) {
  233. SimpleSingleByteEncoding enc = getAdditionalEncoding(index);
  234. int[] arr = new int[enc.getLastChar() - enc.getFirstChar() + 1];
  235. for (int i = 0, c = arr.length; i < c; i++) {
  236. NamedCharacter nc = enc.getCharacterForIndex(enc.getFirstChar() + i);
  237. UnencodedCharacter uc = (UnencodedCharacter)this.unencodedCharacters.get(
  238. new Character(nc.getSingleUnicodeValue()));
  239. arr[i] = uc.getWidth();
  240. }
  241. return arr;
  242. }
  243. private static final class UnencodedCharacter {
  244. private NamedCharacter character;
  245. private int width;
  246. public UnencodedCharacter(NamedCharacter character, int width) {
  247. this.character = character;
  248. this.width = width;
  249. }
  250. public NamedCharacter getCharacter() {
  251. return this.character;
  252. }
  253. public int getWidth() {
  254. return this.width;
  255. }
  256. /** {@inheritDoc} */
  257. public String toString() {
  258. return getCharacter().toString();
  259. }
  260. }
  261. }