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.

AWTFontMetrics.java 8.5KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284
  1. /*
  2. * Copyright 1999-2004 The Apache Software Foundation.
  3. *
  4. * Licensed under the Apache License, Version 2.0 (the "License");
  5. * you may not use this file except in compliance with the License.
  6. * You may obtain a copy of the License at
  7. *
  8. * http://www.apache.org/licenses/LICENSE-2.0
  9. *
  10. * Unless required by applicable law or agreed to in writing, software
  11. * distributed under the License is distributed on an "AS IS" BASIS,
  12. * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
  13. * See the License for the specific language governing permissions and
  14. * limitations under the License.
  15. */
  16. /* $Id$ */
  17. package org.apache.fop.render.awt;
  18. // Java
  19. import java.awt.Font;
  20. import java.awt.Graphics2D;
  21. import java.awt.geom.Rectangle2D;
  22. import java.awt.FontMetrics;
  23. import java.awt.font.TextLayout;
  24. /**
  25. * This is a FontMetrics to be used for AWT rendering.
  26. * It instanciates a font, depening on family and style
  27. * values. The java.awt.FontMetrics for this font is then
  28. * created to be used for the actual measurement.
  29. * Since layout is word by word and since it is expected that
  30. * two subsequent words often share the same style, the
  31. * Font and FontMetrics is buffered and only changed if needed.
  32. * <p>
  33. * Since FontState and FontInfo multiply all factors by
  34. * size, we assume a "standard" font of FONT_SIZE.
  35. */
  36. public class AWTFontMetrics {
  37. /**
  38. * Font size standard used for metric measurements
  39. */
  40. public static final int FONT_SIZE = 1;
  41. /**
  42. * This factor multiplies the calculated values to scale
  43. * to FOP internal measurements
  44. */
  45. public static final int FONT_FACTOR = (1000 * 1000) / FONT_SIZE;
  46. /**
  47. * The width of all 256 character, if requested
  48. */
  49. private int width[] = null;
  50. /**
  51. * The typical height of a small cap latter
  52. */
  53. private int xHeight = 0;
  54. /**
  55. * Buffered font.
  56. * f1 is bufferd for metric measurements during layout.
  57. * fSized is buffered for display purposes
  58. */
  59. private Font f1 = null; // , fSized = null;
  60. /**
  61. * The family type of the font last used
  62. */
  63. private String family = "";
  64. /**
  65. * The style of the font last used
  66. */
  67. private int style = 0;
  68. /**
  69. * The size of the font last used
  70. */
  71. private float size = 0;
  72. /**
  73. * The FontMetrics object used to calculate character width etc.
  74. */
  75. private FontMetrics fmt = null;
  76. /**
  77. * Temp graphics object needed to get the font metrics
  78. */
  79. private Graphics2D graphics;
  80. /**
  81. * Constructs a new Font-metrics.
  82. * @param graphics a temp graphics object - this is needed so
  83. * that we can get an instance of java.awt.FontMetrics
  84. */
  85. public AWTFontMetrics(Graphics2D graphics) {
  86. this.graphics = graphics;
  87. }
  88. /**
  89. * Determines the font ascent of the Font described by this
  90. * FontMetrics object
  91. * @param family font family (java name) to use
  92. * @param style font style (java def.) to use
  93. * @param size font size
  94. * @return ascent in milliponts
  95. */
  96. public int getAscender(String family, int style, int size) {
  97. setFont(family, style, size);
  98. return FONT_FACTOR * fmt.getAscent();
  99. // // workaround for sun bug on FontMetrics.getAscent()
  100. // // http://developer.java.sun.com/developer/bugParade/bugs/4399887.html
  101. // int realAscent = fmt.getAscent()
  102. // - (fmt.getDescent() + fmt.getLeading());
  103. // return FONT_FACTOR * realAscent;
  104. }
  105. /**
  106. * The size of a capital letter measured from the font's baseline
  107. * @param family font family
  108. * @param style font style
  109. * @param size font size
  110. * @return capital height in millipoints
  111. */
  112. public int getCapHeight(String family, int style, int size) {
  113. // currently just gets Ascent value but maybe should use
  114. // getMaxAcent() at some stage
  115. return getAscender(family, style, size);
  116. }
  117. /**
  118. * Determines the font descent of the Font described by this
  119. * FontMetrics object
  120. * @param family font family (jave name) to use
  121. * @param style font style (jave def.) to use
  122. * @param size font size
  123. * @return descent in milliponts
  124. */
  125. public int getDescender(String family, int style, int size) {
  126. setFont(family, style, size);
  127. return (-1 * FONT_FACTOR * fmt.getDescent());
  128. }
  129. /**
  130. * Determines the typical font height of a small cap letter
  131. * FontMetrics object
  132. * @param family font family (jave name) to use
  133. * @param style font style (jave def.) to use
  134. * @param size font size
  135. * @return font height in milliponts
  136. */
  137. public int getXHeight(String family, int style, int size) {
  138. setFont(family, style, size);
  139. return (FONT_FACTOR * xHeight);
  140. }
  141. /**
  142. * Returns width (in 1/1000ths of point size) of character at
  143. * code point i
  144. * @param i the character for which to get the width
  145. * @param family font family (jave name) to use
  146. * @param style font style (jave def.) to use
  147. * @param size font size
  148. * @return character width in millipoints
  149. */
  150. public int width(int i, String family, int style, int size) {
  151. int w;
  152. setFont(family, style, size);
  153. // the output seems to look a little better if the
  154. // space is rendered larger than given by
  155. // the FontMetrics object
  156. // TODO find out why
  157. if (i <= 32) {
  158. w = (int)(1.4 * fmt.charWidth(i) * FONT_FACTOR);
  159. } else {
  160. w = (fmt.charWidth(i) * FONT_FACTOR);
  161. }
  162. return w;
  163. }
  164. /**
  165. * Return widths (in 1/1000ths of point size) of all
  166. * characters
  167. * @param family font family (jave name) to use
  168. * @param style font style (jave def.) to use
  169. * @param size font size
  170. * @return array of character widths in millipoints
  171. */
  172. public int[] getWidths(String family, int style, int size) {
  173. int i;
  174. if (width == null) {
  175. width = new int[256];
  176. }
  177. setFont(family, style, size);
  178. for (i = 0; i < 256; i++) {
  179. width[i] = FONT_FACTOR * fmt.charWidth(i);
  180. }
  181. return width;
  182. }
  183. /**
  184. * Checks whether the font for which values are
  185. * requested is the one used immediately before or
  186. * whether it is a new one
  187. * @param family font family (jave name) to use
  188. * @param style font style (jave def.) to use
  189. * @param size font size
  190. * @return true if the font was changed, false otherwise
  191. */
  192. private boolean setFont(String family, int style, int size) {
  193. boolean changed = false;
  194. Rectangle2D rect;
  195. TextLayout layout;
  196. int s = (int)(size / 1000f);
  197. if (f1 == null) {
  198. f1 = new Font(family, style, s);
  199. fmt = graphics.getFontMetrics(f1);
  200. changed = true;
  201. } else {
  202. if ((this.style != style) || !this.family.equals(family)
  203. || this.size != s) {
  204. if (family.equals(this.family)) {
  205. f1 = f1.deriveFont(style, s);
  206. } else {
  207. f1 = new Font(family, style, s);
  208. }
  209. fmt = graphics.getFontMetrics(f1);
  210. changed = true;
  211. }
  212. // else the font is unchanged from last time
  213. }
  214. if (changed) {
  215. layout = new TextLayout("m", f1, graphics.getFontRenderContext());
  216. rect = layout.getBounds();
  217. xHeight = (int)rect.getHeight();
  218. }
  219. // save the family and style for later comparison
  220. this.family = family;
  221. this.style = style;
  222. this.size = s;
  223. return changed;
  224. }
  225. /**
  226. * Returns a java.awt.Font instance for the desired
  227. * family, style and size type.
  228. * This is here, so that the font-mapping
  229. * of FOP-defined fonts to java-fonts can be done
  230. * in one place and does not need to occur in
  231. * AWTFontRenderer.
  232. * @param family font family (jave name) to use
  233. * @param style font style (jave def.) to use
  234. * @param size font size
  235. * @return font with the desired characeristics.
  236. */
  237. public java.awt.Font getFont(String family, int style, int size) {
  238. setFont(family, style, size);
  239. return f1;
  240. /*
  241. * if( setFont(family,style, size) ) fSized = null;
  242. * if( fSized == null || this.size != size ) {
  243. * fSized = f1.deriveFont( size / 1000f );
  244. * }
  245. * this.size = size;
  246. * return fSized;
  247. */
  248. }
  249. }