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.

DefaultFontConfig.java 12KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343
  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.ArrayList;
  20. import java.util.Collections;
  21. import java.util.List;
  22. import org.apache.avalon.framework.configuration.Configuration;
  23. import org.apache.avalon.framework.configuration.ConfigurationException;
  24. import org.apache.commons.logging.Log;
  25. import org.apache.commons.logging.LogFactory;
  26. import org.apache.fop.apps.FOPException;
  27. import org.apache.fop.events.EventProducer;
  28. import org.apache.fop.util.LogUtil;
  29. /**
  30. * The font configuration data for the more generic fonts such as TTF and Type1, that are used by
  31. * most the renderers.
  32. */
  33. public final class DefaultFontConfig implements FontConfig {
  34. private static final Log log = LogFactory.getLog(DefaultFontConfig.class);
  35. private final List<Directory> directories = new ArrayList<Directory>();
  36. private final List<Font> fonts = new ArrayList<Font>();
  37. private final List<String> referencedFontFamilies = new ArrayList<String>();
  38. private final boolean autoDetectFonts;
  39. private DefaultFontConfig(boolean autoDetectFonts) {
  40. this.autoDetectFonts = autoDetectFonts;
  41. }
  42. /**
  43. * Parses the morge generic font information.
  44. */
  45. public static final class DefaultFontConfigParser implements FontConfig.FontConfigParser {
  46. /**
  47. * Parses the font configuration and return the configuration object.
  48. *
  49. * @param cfg the configuration data
  50. * @param strict whether or not to enforce strict validation
  51. * @return the font configuration object
  52. * @throws FOPException if an error occurs when creating the configuration object
  53. */
  54. public DefaultFontConfig parse(Configuration cfg, boolean strict) throws FOPException {
  55. return new ParserHelper(cfg, strict).instance;
  56. }
  57. /** {@inheritDoc} */
  58. public FontConfig parse(Configuration cfg, FontManager fontManager, boolean strict,
  59. EventProducer eventProducer) throws FOPException {
  60. return parse(cfg, strict);
  61. }
  62. }
  63. private static final class ParserHelper {
  64. private boolean strict;
  65. private Configuration fontInfoCfg;
  66. private DefaultFontConfig instance;
  67. private ParserHelper(Configuration cfg, boolean strict) throws FOPException {
  68. if (cfg == null || cfg.getChild("fonts", false) == null) {
  69. instance = null;
  70. } else {
  71. this.strict = strict;
  72. this.fontInfoCfg = cfg.getChild("fonts", false);
  73. instance = new DefaultFontConfig(fontInfoCfg.getChild("auto-detect", false) != null);
  74. parse();
  75. }
  76. }
  77. private void parse() throws FOPException {
  78. parseFonts();
  79. parseReferencedFonts();
  80. parseDirectories();
  81. }
  82. private void parseFonts() throws FOPException {
  83. for (Configuration fontCfg : fontInfoCfg.getChildren("font")) {
  84. String embed = fontCfg.getAttribute("embed-url", null);
  85. if (embed == null) {
  86. LogUtil.handleError(log, "Font configuration without embed-url attribute",
  87. strict);
  88. continue;
  89. }
  90. Font font = new Font(fontCfg.getAttribute("metrics-url", null), embed,
  91. fontCfg.getAttribute("sub-font", null), fontCfg.getAttributeAsBoolean(
  92. "kerning", true), fontCfg.getAttributeAsBoolean("advanced", true),
  93. fontCfg.getAttribute("encoding-mode", EncodingMode.AUTO.getName()),
  94. fontCfg.getAttribute("embedding-mode", EncodingMode.AUTO.getName()));
  95. instance.fonts.add(font);
  96. boolean hasTriplets = false;
  97. for (Configuration tripletCfg : fontCfg.getChildren("font-triplet")) {
  98. FontTriplet fontTriplet = getFontTriplet(tripletCfg, strict);
  99. font.tripletList.add(fontTriplet);
  100. hasTriplets = true;
  101. }
  102. // no font triplet info
  103. if (!hasTriplets) {
  104. LogUtil.handleError(log, "font without font-triplet", strict);
  105. }
  106. }
  107. }
  108. private void parseReferencedFonts() throws FOPException {
  109. Configuration referencedFontsCfg = fontInfoCfg.getChild("referenced-fonts", false);
  110. if (referencedFontsCfg != null) {
  111. for (Configuration match : referencedFontsCfg.getChildren("match")) {
  112. try {
  113. instance.referencedFontFamilies.add(match.getAttribute("font-family"));
  114. } catch (ConfigurationException ce) {
  115. LogUtil.handleException(log, ce, strict);
  116. continue;
  117. }
  118. }
  119. }
  120. }
  121. private void parseDirectories() throws FOPException {
  122. for (Configuration directoriesCfg : fontInfoCfg.getChildren("directory")) {
  123. boolean recursive = directoriesCfg.getAttributeAsBoolean("recursive", false);
  124. String directory;
  125. try {
  126. directory = directoriesCfg.getValue();
  127. } catch (ConfigurationException e) {
  128. LogUtil.handleException(log, e, strict);
  129. continue;
  130. }
  131. if (directory == null) {
  132. LogUtil.handleException(log,
  133. new FOPException("directory defined without value"), strict);
  134. continue;
  135. }
  136. instance.directories.add(new Directory(directory, recursive));
  137. }
  138. }
  139. /**
  140. * Creates a new FontTriplet given a triple Configuration
  141. *
  142. * @param tripletCfg a triplet configuration
  143. * @return a font triplet font key
  144. * @throws FOPException thrown if a FOP exception occurs
  145. */
  146. private FontTriplet getFontTriplet(Configuration tripletCfg, boolean strict)
  147. throws FOPException {
  148. try {
  149. String name = tripletCfg.getAttribute("name");
  150. if (name == null) {
  151. LogUtil.handleError(log, "font-triplet without name", strict);
  152. return null;
  153. }
  154. String weightStr = tripletCfg.getAttribute("weight");
  155. if (weightStr == null) {
  156. LogUtil.handleError(log, "font-triplet without weight", strict);
  157. return null;
  158. }
  159. int weight = FontUtil.parseCSS2FontWeight(FontUtil.stripWhiteSpace(weightStr));
  160. String style = tripletCfg.getAttribute("style");
  161. if (style == null) {
  162. LogUtil.handleError(log, "font-triplet without style", strict);
  163. return null;
  164. } else {
  165. style = FontUtil.stripWhiteSpace(style);
  166. }
  167. return FontInfo.createFontKey(name, style, weight);
  168. } catch (ConfigurationException e) {
  169. LogUtil.handleException(log, e, strict);
  170. }
  171. return null;
  172. }
  173. }
  174. /**
  175. * Returns the list of fonts that were parsed.
  176. * @return a list of fonts
  177. */
  178. public List<Font> getFonts() {
  179. return Collections.unmodifiableList(fonts);
  180. }
  181. /**
  182. * Returns a list of directories that were parsed.
  183. * @return a list of directories
  184. */
  185. public List<Directory> getDirectories() {
  186. return Collections.unmodifiableList(directories);
  187. }
  188. /**
  189. * Returns a list of referenced font families.
  190. * @return the referenced font families
  191. */
  192. public List<String> getReferencedFontFamily() {
  193. return Collections.unmodifiableList(referencedFontFamilies);
  194. }
  195. /**
  196. * Whether or not to enable auto-detecting of fonts in the system.
  197. * @return true to enable auto-detect
  198. */
  199. public boolean isAutoDetectFonts() {
  200. return autoDetectFonts;
  201. }
  202. /**
  203. * The directory to find fonts within.
  204. */
  205. public static final class Directory {
  206. private final String directory;
  207. private final boolean recursive;
  208. private Directory(String directory, boolean recurse) {
  209. this.directory = directory;
  210. this.recursive = recurse;
  211. }
  212. /**
  213. * Returns a String representing the directory to find fonts within.
  214. * @return the directory
  215. */
  216. public String getDirectory() {
  217. return directory;
  218. }
  219. /**
  220. * Returns whether or not to recurse through the directory when finding fonts.
  221. * @return true to recurse through the directory and sub-directories
  222. */
  223. public boolean isRecursive() {
  224. return recursive;
  225. }
  226. }
  227. /**
  228. * Represents a font object within the FOP conf.
  229. */
  230. public static final class Font {
  231. private final String metrics;
  232. private final String embedUri;
  233. private final String subFont;
  234. private final boolean kerning;
  235. private final boolean advanced;
  236. private final String encodingMode;
  237. private final String embeddingMode;
  238. public String getEncodingMode() {
  239. return encodingMode;
  240. }
  241. private final List<FontTriplet> tripletList = new ArrayList<FontTriplet>();
  242. public List<FontTriplet> getTripletList() {
  243. return Collections.unmodifiableList(tripletList);
  244. }
  245. private Font(String metrics, String embed, String subFont, boolean kerning,
  246. boolean advanced, String encodingMode, String embeddingMode) {
  247. this.metrics = metrics;
  248. this.embedUri = embed;
  249. this.subFont = subFont;
  250. this.kerning = kerning;
  251. this.advanced = advanced;
  252. this.encodingMode = encodingMode;
  253. this.embeddingMode = embeddingMode;
  254. }
  255. /**
  256. * Whether or not to allow kerning of glyphs.
  257. * @return true to allow glyph kerning
  258. */
  259. public boolean isKerning() {
  260. return kerning;
  261. }
  262. public boolean isAdvanced() {
  263. return advanced;
  264. }
  265. /**
  266. * Gets the String representing the metrics file.
  267. * @return the metrics file
  268. */
  269. public String getMetrics() {
  270. return metrics;
  271. }
  272. /**
  273. * Gets the URI of the font to embed.
  274. * @return the font URI
  275. */
  276. public String getEmbedURI() {
  277. return embedUri;
  278. }
  279. /**
  280. * Gets the sub font within, for example, a TTC.
  281. * @return the sub font name
  282. */
  283. public String getSubFont() {
  284. return subFont;
  285. }
  286. public String getEmbeddingMode() {
  287. return embeddingMode;
  288. }
  289. }
  290. }