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.

CustomFont.java 12KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516
  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.io.IOException;
  20. import java.util.Collections;
  21. import java.util.HashMap;
  22. import java.util.HashSet;
  23. import java.util.Map;
  24. import java.util.Set;
  25. import javax.xml.transform.Source;
  26. /**
  27. * Abstract base class for custom fonts loaded from files, for example.
  28. */
  29. public abstract class CustomFont extends Typeface
  30. implements FontDescriptor, MutableFont {
  31. private String fontName = null;
  32. private String fullName = null;
  33. private Set<String> familyNames = null;
  34. private String fontSubName = null;
  35. private String embedFileName = null;
  36. private String embedResourceName = null;
  37. private FontResolver resolver = null;
  38. private EmbeddingMode embeddingMode = EmbeddingMode.AUTO;
  39. private int capHeight = 0;
  40. private int xHeight = 0;
  41. private int ascender = 0;
  42. private int descender = 0;
  43. private int[] fontBBox = {0, 0, 0, 0};
  44. private int flags = 4;
  45. private int weight = 0; //0 means unknown weight
  46. private int stemV = 0;
  47. private int italicAngle = 0;
  48. private int missingWidth = 0;
  49. private FontType fontType = FontType.TYPE1;
  50. private int firstChar = 0;
  51. private int lastChar = 255;
  52. private Map<Integer, Map<Integer, Integer>> kerning;
  53. private boolean useKerning = true;
  54. private boolean useAdvanced = true;
  55. /** the character map, mapping Unicode ranges to glyph indices. */
  56. protected CMapSegment[] cmap;
  57. /** {@inheritDoc} */
  58. public String getFontName() {
  59. return fontName;
  60. }
  61. /** {@inheritDoc} */
  62. public String getEmbedFontName() {
  63. return getFontName();
  64. }
  65. /** {@inheritDoc} */
  66. public String getFullName() {
  67. return fullName;
  68. }
  69. /**
  70. * Returns the font family names.
  71. * @return the font family names (a Set of Strings)
  72. */
  73. public Set<String> getFamilyNames() {
  74. return Collections.unmodifiableSet(this.familyNames);
  75. }
  76. /**
  77. * Returns the font family name stripped of whitespace.
  78. * @return the stripped font family
  79. * @see FontUtil#stripWhiteSpace(String)
  80. */
  81. public String getStrippedFontName() {
  82. return FontUtil.stripWhiteSpace(getFontName());
  83. }
  84. /**
  85. * Returns font's subfamily name.
  86. * @return the font's subfamily name
  87. */
  88. public String getFontSubName() {
  89. return fontSubName;
  90. }
  91. /**
  92. * Returns an URI representing an embeddable font file. The URI will often
  93. * be a filename or an URL.
  94. * @return URI to an embeddable font file or null if not available.
  95. */
  96. public String getEmbedFileName() {
  97. return embedFileName;
  98. }
  99. /**
  100. * Returns the embedding mode for this font.
  101. * @return embedding mode
  102. */
  103. public EmbeddingMode getEmbeddingMode() {
  104. return embeddingMode;
  105. }
  106. /**
  107. * Returns a Source representing an embeddable font file.
  108. * @return Source for an embeddable font file
  109. * @throws IOException if embedFileName is not null but Source is not found
  110. */
  111. public Source getEmbedFileSource() throws IOException {
  112. Source result = null;
  113. if (resolver != null && embedFileName != null) {
  114. result = resolver.resolve(embedFileName);
  115. if (result == null) {
  116. throw new IOException("Unable to resolve Source '"
  117. + embedFileName + "' for embedded font");
  118. }
  119. }
  120. return result;
  121. }
  122. /**
  123. * Returns the lookup name to an embeddable font file available as a
  124. * resource.
  125. * (todo) Remove this method, this should be done using a resource: URI.
  126. * @return the lookup name
  127. */
  128. public String getEmbedResourceName() {
  129. return embedResourceName;
  130. }
  131. /**
  132. * {@inheritDoc}
  133. */
  134. public int getAscender() {
  135. return ascender;
  136. }
  137. /**
  138. * {@inheritDoc}
  139. */
  140. public int getDescender() {
  141. return descender;
  142. }
  143. /**
  144. * {@inheritDoc}
  145. */
  146. public int getCapHeight() {
  147. return capHeight;
  148. }
  149. /**
  150. * {@inheritDoc}
  151. */
  152. public int getAscender(int size) {
  153. return size * ascender;
  154. }
  155. /**
  156. * {@inheritDoc}
  157. */
  158. public int getDescender(int size) {
  159. return size * descender;
  160. }
  161. /**
  162. * {@inheritDoc}
  163. */
  164. public int getCapHeight(int size) {
  165. return size * capHeight;
  166. }
  167. /**
  168. * {@inheritDoc}
  169. */
  170. public int getXHeight(int size) {
  171. return size * xHeight;
  172. }
  173. /**
  174. * {@inheritDoc}
  175. */
  176. public int[] getFontBBox() {
  177. return fontBBox;
  178. }
  179. /** {@inheritDoc} */
  180. public int getFlags() {
  181. return flags;
  182. }
  183. /** {@inheritDoc} */
  184. public boolean isSymbolicFont() {
  185. return ((getFlags() & 4) != 0) || "ZapfDingbatsEncoding".equals(getEncodingName());
  186. //Note: The check for ZapfDingbats is necessary as the PFM does not reliably indicate
  187. //if a font is symbolic.
  188. }
  189. /**
  190. * Returns the font weight (100, 200...800, 900). This value may be different from the
  191. * one that was actually used to register the font.
  192. * @return the font weight (or 0 if the font weight is unknown)
  193. */
  194. public int getWeight() {
  195. return this.weight;
  196. }
  197. /**
  198. * {@inheritDoc}
  199. */
  200. public int getStemV() {
  201. return stemV;
  202. }
  203. /**
  204. * {@inheritDoc}
  205. */
  206. public int getItalicAngle() {
  207. return italicAngle;
  208. }
  209. /**
  210. * Returns the width to be used when no width is available.
  211. * @return a character width
  212. */
  213. public int getMissingWidth() {
  214. return missingWidth;
  215. }
  216. /**
  217. * {@inheritDoc}
  218. */
  219. public FontType getFontType() {
  220. return fontType;
  221. }
  222. /**
  223. * Returns the index of the first character defined in this font.
  224. * @return the index of the first character
  225. */
  226. public int getFirstChar() {
  227. return firstChar;
  228. }
  229. /**
  230. * Returns the index of the last character defined in this font.
  231. * @return the index of the last character
  232. */
  233. public int getLastChar() {
  234. return lastChar;
  235. }
  236. /**
  237. * Used to determine if kerning is enabled.
  238. * @return True if kerning is enabled.
  239. */
  240. public boolean isKerningEnabled() {
  241. return useKerning;
  242. }
  243. /**
  244. * {@inheritDoc}
  245. */
  246. public final boolean hasKerningInfo() {
  247. return (isKerningEnabled() && (kerning != null) && !kerning.isEmpty());
  248. }
  249. /**
  250. * {@inheritDoc}
  251. */
  252. public final Map<Integer, Map<Integer, Integer>> getKerningInfo() {
  253. if (hasKerningInfo()) {
  254. return kerning;
  255. } else {
  256. return Collections.emptyMap();
  257. }
  258. }
  259. /**
  260. * Used to determine if advanced typographic features are enabled.
  261. * By default, this is false, but may be overridden by subclasses.
  262. * @return true if enabled.
  263. */
  264. public boolean isAdvancedEnabled() {
  265. return useAdvanced;
  266. }
  267. /* ---- MutableFont interface ---- */
  268. /** {@inheritDoc} */
  269. public void setFontName(String name) {
  270. this.fontName = name;
  271. }
  272. /** {@inheritDoc} */
  273. public void setFullName(String name) {
  274. this.fullName = name;
  275. }
  276. /** {@inheritDoc} */
  277. public void setFamilyNames(Set<String> names) {
  278. this.familyNames = new HashSet<String>(names);
  279. }
  280. /**
  281. * Sets the font's subfamily name.
  282. * @param subFamilyName the subfamily name of the font
  283. */
  284. public void setFontSubFamilyName(String subFamilyName) {
  285. this.fontSubName = subFamilyName;
  286. }
  287. /**
  288. * {@inheritDoc}
  289. */
  290. public void setEmbedFileName(String path) {
  291. this.embedFileName = path;
  292. }
  293. /**
  294. * {@inheritDoc}
  295. */
  296. public void setEmbedResourceName(String name) {
  297. this.embedResourceName = name;
  298. }
  299. /**
  300. * {@inheritDoc}
  301. */
  302. public void setEmbeddingMode(EmbeddingMode embeddingMode) {
  303. this.embeddingMode = embeddingMode;
  304. }
  305. /**
  306. * {@inheritDoc}
  307. */
  308. public void setCapHeight(int capHeight) {
  309. this.capHeight = capHeight;
  310. }
  311. /**
  312. * Returns the XHeight value of the font.
  313. * @param xHeight the XHeight value
  314. */
  315. public void setXHeight(int xHeight) {
  316. this.xHeight = xHeight;
  317. }
  318. /**
  319. * {@inheritDoc}
  320. */
  321. public void setAscender(int ascender) {
  322. this.ascender = ascender;
  323. }
  324. /**
  325. * {@inheritDoc}
  326. */
  327. public void setDescender(int descender) {
  328. this.descender = descender;
  329. }
  330. /**
  331. * {@inheritDoc}
  332. */
  333. public void setFontBBox(int[] bbox) {
  334. this.fontBBox = bbox;
  335. }
  336. /**
  337. * {@inheritDoc}
  338. */
  339. public void setFlags(int flags) {
  340. this.flags = flags;
  341. }
  342. /**
  343. * Sets the font weight. Valid values are 100, 200...800, 900.
  344. * @param weight the font weight
  345. */
  346. public void setWeight(int weight) {
  347. weight = (weight / 100) * 100;
  348. weight = Math.max(100, weight);
  349. weight = Math.min(900, weight);
  350. this.weight = weight;
  351. }
  352. /**
  353. * {@inheritDoc}
  354. */
  355. public void setStemV(int stemV) {
  356. this.stemV = stemV;
  357. }
  358. /**
  359. * {@inheritDoc}
  360. */
  361. public void setItalicAngle(int italicAngle) {
  362. this.italicAngle = italicAngle;
  363. }
  364. /**
  365. * {@inheritDoc}
  366. */
  367. public void setMissingWidth(int width) {
  368. this.missingWidth = width;
  369. }
  370. /**
  371. * {@inheritDoc}
  372. */
  373. public void setFontType(FontType fontType) {
  374. this.fontType = fontType;
  375. }
  376. /**
  377. * {@inheritDoc}
  378. */
  379. public void setFirstChar(int index) {
  380. this.firstChar = index;
  381. }
  382. /**
  383. * {@inheritDoc}
  384. */
  385. public void setLastChar(int index) {
  386. this.lastChar = index;
  387. }
  388. /**
  389. * {@inheritDoc}
  390. */
  391. public void setKerningEnabled(boolean enabled) {
  392. this.useKerning = enabled;
  393. }
  394. /**
  395. * {@inheritDoc}
  396. */
  397. public void setAdvancedEnabled(boolean enabled) {
  398. this.useAdvanced = enabled;
  399. }
  400. /**
  401. * Sets the font resolver. Needed for URI resolution.
  402. * @param resolver the font resolver
  403. */
  404. public void setResolver(FontResolver resolver) {
  405. this.resolver = resolver;
  406. }
  407. /** {@inheritDoc} */
  408. public void putKerningEntry(Integer key, Map<Integer, Integer> value) {
  409. if (kerning == null) {
  410. kerning = new HashMap<Integer, Map<Integer, Integer>>();
  411. }
  412. this.kerning.put(key, value);
  413. }
  414. /**
  415. * Replaces the existing kerning map with a new one.
  416. * @param kerningMap the kerning map (Map<Integer, Map<Integer, Integer>, the integers are
  417. * character codes)
  418. */
  419. public void replaceKerningMap(Map<Integer, Map<Integer, Integer>> kerningMap) {
  420. if (kerningMap == null) {
  421. this.kerning = Collections.emptyMap();
  422. } else {
  423. this.kerning = kerningMap;
  424. }
  425. }
  426. /**
  427. * Sets the character map for this font. It maps all available Unicode characters
  428. * to their glyph indices inside the font.
  429. * @param cmap the character map
  430. */
  431. public void setCMap(CMapSegment[] cmap) {
  432. this.cmap = new CMapSegment[cmap.length];
  433. System.arraycopy(cmap, 0, this.cmap, 0, cmap.length);
  434. }
  435. /**
  436. * Returns the character map for this font. It maps all available Unicode characters
  437. * to their glyph indices inside the font.
  438. * @return the character map
  439. */
  440. public CMapSegment[] getCMap() {
  441. CMapSegment[] copy = new CMapSegment[cmap.length];
  442. System.arraycopy(this.cmap, 0, copy, 0, this.cmap.length);
  443. return copy;
  444. }
  445. }