Du kannst nicht mehr als 25 Themen auswählen Themen müssen mit entweder einem Buchstaben oder einer Ziffer beginnen. Sie können Bindestriche („-“) enthalten und bis zu 35 Zeichen lang sein.

Font.java 9.9KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346
  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.Map;
  20. import org.apache.commons.logging.Log;
  21. import org.apache.commons.logging.LogFactory;
  22. /**
  23. * This class holds font state information and provides access to the font
  24. * metrics.
  25. */
  26. public class Font {
  27. /** Extra Bold font weight */
  28. public static final int WEIGHT_EXTRA_BOLD = 800;
  29. /** Bold font weight */
  30. public static final int WEIGHT_BOLD = 700;
  31. /** Normal font weight */
  32. public static final int WEIGHT_NORMAL = 400;
  33. /** Light font weight */
  34. public static final int WEIGHT_LIGHT = 200;
  35. /** Normal font style */
  36. public static final String STYLE_NORMAL = "normal";
  37. /** Italic font style */
  38. public static final String STYLE_ITALIC = "italic";
  39. /** Oblique font style */
  40. public static final String STYLE_OBLIQUE = "oblique";
  41. /** Inclined font style */
  42. public static final String STYLE_INCLINED = "inclined";
  43. /** Default selection priority */
  44. public static final int PRIORITY_DEFAULT = 0;
  45. /** Default fallback key */
  46. public static final FontTriplet DEFAULT_FONT = new FontTriplet(
  47. "any", STYLE_NORMAL, WEIGHT_NORMAL, PRIORITY_DEFAULT);
  48. /** logger */
  49. private static Log log = LogFactory.getLog(Font.class);
  50. private String fontName;
  51. private FontTriplet triplet;
  52. private int fontSize;
  53. /**
  54. * normal or small-caps font
  55. */
  56. //private int fontVariant;
  57. private FontMetrics metric;
  58. /**
  59. * Main constructor
  60. * @param key key of the font
  61. * @param triplet the font triplet that was used to lookup this font (may be null)
  62. * @param met font metrics
  63. * @param fontSize font size
  64. */
  65. public Font(String key, FontTriplet triplet, FontMetrics met, int fontSize) {
  66. this.fontName = key;
  67. this.triplet = triplet;
  68. this.metric = met;
  69. this.fontSize = fontSize;
  70. }
  71. /**
  72. * Returns the associated font metrics object.
  73. * @return the font metrics
  74. */
  75. public FontMetrics getFontMetrics() {
  76. return this.metric;
  77. }
  78. /**
  79. * Returns the font's ascender.
  80. * @return the ascender
  81. */
  82. public int getAscender() {
  83. return metric.getAscender(fontSize) / 1000;
  84. }
  85. /**
  86. * Returns the font's CapHeight.
  87. * @return the capital height
  88. */
  89. public int getCapHeight() {
  90. return metric.getCapHeight(fontSize) / 1000;
  91. }
  92. /**
  93. * Returns the font's Descender.
  94. * @return the descender
  95. */
  96. public int getDescender() {
  97. return metric.getDescender(fontSize) / 1000;
  98. }
  99. /**
  100. * Returns the font's name.
  101. * @return the font name
  102. */
  103. public String getFontName() {
  104. return fontName;
  105. }
  106. /** @return the font triplet that selected this font */
  107. public FontTriplet getFontTriplet() {
  108. return this.triplet;
  109. }
  110. /**
  111. * Returns the font size
  112. * @return the font size
  113. */
  114. public int getFontSize() {
  115. return fontSize;
  116. }
  117. /**
  118. * Returns the XHeight
  119. * @return the XHeight
  120. */
  121. public int getXHeight() {
  122. return metric.getXHeight(fontSize) / 1000;
  123. }
  124. /** @return true if the font has kerning info */
  125. public boolean hasKerning() {
  126. return metric.hasKerningInfo();
  127. }
  128. /**
  129. * Returns the font's kerning table
  130. * @return the kerning table
  131. */
  132. public Map getKerning() {
  133. if (metric.hasKerningInfo()) {
  134. return metric.getKerningInfo();
  135. } else {
  136. return java.util.Collections.EMPTY_MAP;
  137. }
  138. }
  139. /**
  140. * Returns the amount of kerning between two characters.
  141. * @param ch1 first character
  142. * @param ch2 second character
  143. * @return the distance to adjust for kerning, 0 if there's no kerning
  144. */
  145. public int getKernValue(char ch1, char ch2) {
  146. Map kernPair = (Map)getKerning().get(new Integer(ch1));
  147. if (kernPair != null) {
  148. Integer width = (Integer)kernPair.get(new Integer(ch2));
  149. if (width != null) {
  150. return width.intValue();
  151. }
  152. }
  153. return 0;
  154. }
  155. /**
  156. * Returns the width of a character
  157. * @param charnum character to look up
  158. * @return width of the character
  159. */
  160. public int getWidth(int charnum) {
  161. // returns width of given character number in millipoints
  162. return (metric.getWidth(charnum, fontSize) / 1000);
  163. }
  164. /**
  165. * Map a java character (unicode) to a font character.
  166. * Default uses CodePointMapping.
  167. * @param c character to map
  168. * @return the mapped character
  169. */
  170. public char mapChar(char c) {
  171. if (metric instanceof org.apache.fop.fonts.Typeface) {
  172. return ((org.apache.fop.fonts.Typeface)metric).mapChar(c);
  173. }
  174. // Use default CodePointMapping
  175. char d = CodePointMapping.getMapping("WinAnsiEncoding").mapChar(c);
  176. if (d != SingleByteEncoding.NOT_FOUND_CODE_POINT) {
  177. c = d;
  178. } else {
  179. log.warn("Glyph " + (int) c + " not available in font " + fontName);
  180. c = '#';
  181. }
  182. return c;
  183. }
  184. /**
  185. * Determines whether this font contains a particular character/glyph.
  186. * @param c character to check
  187. * @return True if the character is supported, Falso otherwise
  188. */
  189. public boolean hasChar(char c) {
  190. if (metric instanceof org.apache.fop.fonts.Typeface) {
  191. return ((org.apache.fop.fonts.Typeface)metric).hasChar(c);
  192. } else {
  193. // Use default CodePointMapping
  194. return (CodePointMapping.getMapping("WinAnsiEncoding").mapChar(c) > 0);
  195. }
  196. }
  197. /**
  198. * {@inheritDoc}
  199. */
  200. public String toString() {
  201. StringBuffer sbuf = new StringBuffer();
  202. sbuf.append('(');
  203. /*
  204. sbuf.append(fontFamily);
  205. sbuf.append(',');*/
  206. sbuf.append(fontName);
  207. sbuf.append(',');
  208. sbuf.append(fontSize);
  209. /*
  210. sbuf.append(',');
  211. sbuf.append(fontStyle);
  212. sbuf.append(',');
  213. sbuf.append(fontWeight);*/
  214. sbuf.append(')');
  215. return sbuf.toString();
  216. }
  217. /**
  218. * Helper method for getting the width of a unicode char
  219. * from the current fontstate.
  220. * This also performs some guessing on widths on various
  221. * versions of space that might not exists in the font.
  222. * @param c character to inspect
  223. * @return the width of the character
  224. */
  225. public int getCharWidth(char c) {
  226. int width;
  227. if ((c == '\n') || (c == '\r') || (c == '\t') || (c == '\u00A0')) {
  228. width = getCharWidth(' ');
  229. } else {
  230. if (hasChar(c)) {
  231. width = getWidth(mapChar(c));
  232. } else {
  233. width = -1;
  234. }
  235. if (width <= 0) {
  236. // Estimate the width of spaces not represented in
  237. // the font
  238. int em = getFontSize(); //http://en.wikipedia.org/wiki/Em_(typography)
  239. int en = em / 2; //http://en.wikipedia.org/wiki/En_(typography)
  240. if (c == ' ') {
  241. width = em;
  242. } else if (c == '\u2000') {
  243. width = en;
  244. } else if (c == '\u2001') {
  245. width = em;
  246. } else if (c == '\u2002') {
  247. width = em / 2;
  248. } else if (c == '\u2003') {
  249. width = getFontSize();
  250. } else if (c == '\u2004') {
  251. width = em / 3;
  252. } else if (c == '\u2005') {
  253. width = em / 4;
  254. } else if (c == '\u2006') {
  255. width = em / 6;
  256. } else if (c == '\u2007') {
  257. width = getCharWidth('0');
  258. } else if (c == '\u2008') {
  259. width = getCharWidth('.');
  260. } else if (c == '\u2009') {
  261. width = em / 5;
  262. } else if (c == '\u200A') {
  263. width = em / 10;
  264. } else if (c == '\u200B') {
  265. width = 0;
  266. } else if (c == '\u202F') {
  267. width = getCharWidth(' ') / 2;
  268. } else if (c == '\u2060') {
  269. width = 0;
  270. } else if (c == '\u3000') {
  271. width = getCharWidth(' ') * 2;
  272. } else if (c == '\ufeff') {
  273. width = 0;
  274. } else {
  275. //Will be internally replaced by "#" if not found
  276. width = getWidth(mapChar(c));
  277. }
  278. }
  279. }
  280. return width;
  281. }
  282. /**
  283. * Calculates the word width.
  284. * @param word text to get width for
  285. * @return the width of the text
  286. */
  287. public int getWordWidth(String word) {
  288. if (word == null) {
  289. return 0;
  290. }
  291. int wordLength = word.length();
  292. int width = 0;
  293. char[] characters = new char[wordLength];
  294. word.getChars(0, wordLength, characters, 0);
  295. for (int i = 0; i < wordLength; i++) {
  296. width += getCharWidth(characters[i]);
  297. }
  298. return width;
  299. }
  300. }