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.

AFPRendererConfig.java 15KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375
  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.render.afp;
  19. import java.net.URI;
  20. import java.net.URISyntaxException;
  21. import java.util.EnumMap;
  22. import org.apache.commons.logging.Log;
  23. import org.apache.commons.logging.LogFactory;
  24. import org.apache.fop.afp.AFPConstants;
  25. import org.apache.fop.afp.AFPDataObjectInfo;
  26. import org.apache.fop.afp.AFPEventProducer;
  27. import org.apache.fop.afp.AFPResourceLevel;
  28. import org.apache.fop.afp.AFPResourceLevelDefaults;
  29. import org.apache.fop.afp.modca.triplets.MappingOptionTriplet;
  30. import org.apache.fop.apps.FOPException;
  31. import org.apache.fop.apps.FOUserAgent;
  32. import org.apache.fop.apps.MimeConstants;
  33. import org.apache.fop.apps.io.InternalResourceResolver;
  34. import org.apache.fop.configuration.Configuration;
  35. import org.apache.fop.configuration.ConfigurationException;
  36. import org.apache.fop.fonts.FontManager;
  37. import org.apache.fop.render.RendererConfig;
  38. import org.apache.fop.render.afp.AFPFontConfig.AFPFontInfoConfigParser;
  39. import org.apache.fop.util.LogUtil;
  40. import static org.apache.fop.render.afp.AFPRendererConfig.ImagesModeOptions.MODE_COLOR;
  41. import static org.apache.fop.render.afp.AFPRendererConfig.ImagesModeOptions.MODE_GRAYSCALE;
  42. import static org.apache.fop.render.afp.AFPRendererOption.DEFAULT_RESOURCE_LEVELS;
  43. import static org.apache.fop.render.afp.AFPRendererOption.GOCA;
  44. import static org.apache.fop.render.afp.AFPRendererOption.GOCA_TEXT;
  45. import static org.apache.fop.render.afp.AFPRendererOption.IMAGES;
  46. import static org.apache.fop.render.afp.AFPRendererOption.IMAGES_DITHERING_QUALITY;
  47. import static org.apache.fop.render.afp.AFPRendererOption.IMAGES_FS45;
  48. import static org.apache.fop.render.afp.AFPRendererOption.IMAGES_JPEG;
  49. import static org.apache.fop.render.afp.AFPRendererOption.IMAGES_MAPPING_OPTION;
  50. import static org.apache.fop.render.afp.AFPRendererOption.IMAGES_MODE;
  51. import static org.apache.fop.render.afp.AFPRendererOption.IMAGES_NATIVE;
  52. import static org.apache.fop.render.afp.AFPRendererOption.IMAGES_WRAP_PSEG;
  53. import static org.apache.fop.render.afp.AFPRendererOption.JPEG_ALLOW_JPEG_EMBEDDING;
  54. import static org.apache.fop.render.afp.AFPRendererOption.JPEG_BITMAP_ENCODING_QUALITY;
  55. import static org.apache.fop.render.afp.AFPRendererOption.LINE_WIDTH_CORRECTION;
  56. import static org.apache.fop.render.afp.AFPRendererOption.RENDERER_RESOLUTION;
  57. import static org.apache.fop.render.afp.AFPRendererOption.RESOURCE_GROUP_URI;
  58. import static org.apache.fop.render.afp.AFPRendererOption.SHADING;
  59. /**
  60. * The AFP renderer config object.
  61. */
  62. public final class AFPRendererConfig implements RendererConfig {
  63. /**
  64. * An enumeration for the various images modes available to the AFP renderer.
  65. */
  66. public enum ImagesModeOptions {
  67. MODE_GRAYSCALE("b+w", "bits-per-pixel"),
  68. MODE_COLOR("color", "cmyk");
  69. private final String name;
  70. private final String modeAttribute;
  71. private ImagesModeOptions(String name, String modeAttribute) {
  72. this.name = name;
  73. this.modeAttribute = modeAttribute;
  74. }
  75. public String getName() {
  76. return name;
  77. }
  78. public String getModeAttribute() {
  79. return modeAttribute;
  80. }
  81. public static ImagesModeOptions forName(String name) {
  82. for (ImagesModeOptions option : values()) {
  83. if (option.name.equals(name)) {
  84. return option;
  85. }
  86. }
  87. throw new IllegalArgumentException(name);
  88. }
  89. }
  90. private final EnumMap<AFPRendererOption, Object> params
  91. = new EnumMap<AFPRendererOption, Object>(AFPRendererOption.class);
  92. private final EnumMap<ImagesModeOptions, Object> imageModeParams
  93. = new EnumMap<ImagesModeOptions, Object>(ImagesModeOptions.class);
  94. private final AFPFontConfig fontConfig;
  95. private AFPRendererConfig(AFPFontConfig fontConfig) {
  96. this.fontConfig = fontConfig;
  97. }
  98. public AFPFontConfig getFontInfoConfig() {
  99. return fontConfig;
  100. }
  101. public Boolean isColorImages() {
  102. return getParam(IMAGES_MODE, Boolean.class);
  103. }
  104. public Boolean isCmykImagesSupported() {
  105. if (!isColorImages()) {
  106. throw new IllegalStateException();
  107. }
  108. return Boolean.class.cast(imageModeParams.get(MODE_COLOR));
  109. }
  110. public Integer getBitsPerPixel() {
  111. if (isColorImages()) {
  112. throw new IllegalStateException();
  113. }
  114. return Integer.class.cast(imageModeParams.get(MODE_GRAYSCALE));
  115. }
  116. public Float getDitheringQuality() {
  117. return getParam(IMAGES_DITHERING_QUALITY, Float.class);
  118. }
  119. public Boolean isNativeImagesSupported() {
  120. return getParam(IMAGES_NATIVE, Boolean.class);
  121. }
  122. public AFPShadingMode getShadingMode() {
  123. return getParam(SHADING, AFPShadingMode.class);
  124. }
  125. public Integer getResolution() {
  126. return getParam(RENDERER_RESOLUTION, Integer.class);
  127. }
  128. public URI getDefaultResourceGroupUri() {
  129. return getParam(RESOURCE_GROUP_URI, URI.class);
  130. }
  131. public AFPResourceLevelDefaults getResourceLevelDefaults() {
  132. return getParam(DEFAULT_RESOURCE_LEVELS, AFPResourceLevelDefaults.class);
  133. }
  134. public Boolean isWrapPseg() {
  135. return getParam(IMAGES_WRAP_PSEG, Boolean.class);
  136. }
  137. public Boolean isFs45() {
  138. return getParam(IMAGES_FS45, Boolean.class);
  139. }
  140. public Boolean allowJpegEmbedding() {
  141. return getParam(JPEG_ALLOW_JPEG_EMBEDDING, Boolean.class);
  142. }
  143. public Float getBitmapEncodingQuality() {
  144. return getParam(JPEG_BITMAP_ENCODING_QUALITY, Float.class);
  145. }
  146. public Float getLineWidthCorrection() {
  147. return getParam(LINE_WIDTH_CORRECTION, Float.class);
  148. }
  149. public Boolean isGocaEnabled() {
  150. return getParam(GOCA, Boolean.class);
  151. }
  152. public Boolean isStrokeGocaText() {
  153. return getParam(GOCA_TEXT, Boolean.class);
  154. }
  155. private <T> T getParam(AFPRendererOption options, Class<T> type) {
  156. assert options.getType().equals(type);
  157. return type.cast(params.get(options));
  158. }
  159. private <T> void setParam(AFPRendererOption option, T value) {
  160. assert option.getType().isInstance(value);
  161. params.put(option, value);
  162. }
  163. /**
  164. * The parser for AFP renderer specific data in the FOP conf.
  165. */
  166. public static final class AFPRendererConfigParser implements RendererConfigParser {
  167. private static final Log LOG = LogFactory.getLog(AFPRendererConfigParser.class);
  168. /** {@inheritDoc} */
  169. public AFPRendererConfig build(FOUserAgent userAgent, Configuration cfg) throws FOPException {
  170. boolean strict = userAgent.validateUserConfigStrictly();
  171. AFPRendererConfig config = null;
  172. AFPEventProducer eventProducer = AFPEventProducer.Provider.get(userAgent.getEventBroadcaster());
  173. try {
  174. config = new ParserHelper(cfg, userAgent.getFontManager(), strict, eventProducer).config;
  175. } catch (ConfigurationException e) {
  176. LogUtil.handleException(LOG, e, strict);
  177. }
  178. return config;
  179. }
  180. /** {@inheritDoc} */
  181. public String getMimeType() {
  182. return MimeConstants.MIME_AFP;
  183. }
  184. }
  185. private static final class ParserHelper {
  186. private static final Log LOG = LogFactory.getLog(ParserHelper.class);
  187. private final AFPRendererConfig config;
  188. private final boolean strict;
  189. private final Configuration cfg;
  190. private ParserHelper(Configuration cfg, FontManager fontManager, boolean strict,
  191. AFPEventProducer eventProducer)
  192. throws ConfigurationException, FOPException {
  193. this.cfg = cfg;
  194. this.strict = strict;
  195. if (cfg != null) {
  196. config = new AFPRendererConfig(new AFPFontInfoConfigParser().parse(cfg,
  197. fontManager, strict, eventProducer));
  198. configure();
  199. } else {
  200. config = new AFPRendererConfig(new AFPFontInfoConfigParser().getEmptyConfig());
  201. }
  202. }
  203. private void configure() throws ConfigurationException, FOPException {
  204. configureImages();
  205. setParam(SHADING, AFPShadingMode.getValueOf(
  206. cfg.getChild(SHADING.getName()).getValue(AFPShadingMode.COLOR.getName())));
  207. Configuration rendererResolutionCfg = cfg.getChild(RENDERER_RESOLUTION.getName(), false);
  208. setParam(RENDERER_RESOLUTION, rendererResolutionCfg == null ? 240
  209. : rendererResolutionCfg.getValueAsInteger(240));
  210. Configuration lineWidthCorrectionCfg = cfg.getChild(LINE_WIDTH_CORRECTION.getName(),
  211. false);
  212. setParam(LINE_WIDTH_CORRECTION, lineWidthCorrectionCfg != null
  213. ? lineWidthCorrectionCfg.getValueAsFloat()
  214. : AFPConstants.LINE_WIDTH_CORRECTION);
  215. Configuration gocaCfg = cfg.getChild(GOCA.getName());
  216. boolean gocaEnabled = gocaCfg.getAttributeAsBoolean("enabled", true);
  217. setParam(GOCA, gocaEnabled);
  218. String strokeGocaText = gocaCfg.getAttribute(GOCA_TEXT.getName(), "default");
  219. setParam(GOCA_TEXT, "stroke".equalsIgnoreCase(strokeGocaText)
  220. || "shapes".equalsIgnoreCase(strokeGocaText));
  221. //TODO remove
  222. createResourceGroupFile();
  223. createResourceLevel();
  224. }
  225. private void setParam(AFPRendererOption option, Object value) {
  226. config.setParam(option, value);
  227. }
  228. private void configureImages() throws ConfigurationException, FOPException {
  229. Configuration imagesCfg = cfg.getChild(IMAGES.getName());
  230. ImagesModeOptions imagesMode = ImagesModeOptions.forName(imagesCfg.getAttribute(
  231. IMAGES_MODE.getName(), MODE_GRAYSCALE.getName()));
  232. boolean colorImages = MODE_COLOR == imagesMode;
  233. setParam(IMAGES_MODE, colorImages);
  234. if (colorImages) {
  235. config.imageModeParams.put(MODE_COLOR, imagesCfg
  236. .getAttributeAsBoolean(imagesMode.getModeAttribute(), false));
  237. } else {
  238. config.imageModeParams.put(MODE_GRAYSCALE,
  239. imagesCfg.getAttributeAsInteger(imagesMode.getModeAttribute(), 8));
  240. }
  241. String dithering = imagesCfg.getAttribute(AFPRendererOption.IMAGES_DITHERING_QUALITY.getName(), "medium");
  242. float dq;
  243. if (dithering.startsWith("min")) {
  244. dq = 0.0f;
  245. } else if (dithering.startsWith("max")) {
  246. dq = 1.0f;
  247. } else {
  248. try {
  249. dq = Float.parseFloat(dithering);
  250. } catch (NumberFormatException nfe) {
  251. //Default value
  252. dq = 0.5f;
  253. }
  254. }
  255. setParam(IMAGES_DITHERING_QUALITY, dq);
  256. setParam(IMAGES_NATIVE, imagesCfg.getAttributeAsBoolean(IMAGES_NATIVE.getName(), false));
  257. setParam(IMAGES_WRAP_PSEG,
  258. imagesCfg.getAttributeAsBoolean(IMAGES_WRAP_PSEG.getName(), false));
  259. setParam(IMAGES_FS45, imagesCfg.getAttributeAsBoolean(IMAGES_FS45.getName(), false));
  260. if ("scale-to-fit".equals(imagesCfg.getAttribute(IMAGES_MAPPING_OPTION.getName(), null))) {
  261. setParam(IMAGES_MAPPING_OPTION, MappingOptionTriplet.SCALE_TO_FILL);
  262. } else {
  263. setParam(IMAGES_MAPPING_OPTION, AFPDataObjectInfo.DEFAULT_MAPPING_OPTION);
  264. }
  265. configureJpegImages(imagesCfg);
  266. }
  267. private void configureJpegImages(Configuration imagesCfg) {
  268. Configuration jpegConfig = imagesCfg.getChild(IMAGES_JPEG.getName());
  269. float bitmapEncodingQuality = 1.0f;
  270. boolean allowJpegEmbedding = false;
  271. if (jpegConfig != null) {
  272. allowJpegEmbedding = jpegConfig.getAttributeAsBoolean(
  273. JPEG_ALLOW_JPEG_EMBEDDING.getName(),
  274. false);
  275. String bitmapEncodingQualityStr = jpegConfig.getAttribute(
  276. JPEG_BITMAP_ENCODING_QUALITY.getName(), null);
  277. if (bitmapEncodingQualityStr != null) {
  278. try {
  279. bitmapEncodingQuality = Float.parseFloat(bitmapEncodingQualityStr);
  280. } catch (NumberFormatException nfe) {
  281. //ignore and leave the default above
  282. }
  283. }
  284. }
  285. setParam(JPEG_BITMAP_ENCODING_QUALITY, bitmapEncodingQuality);
  286. setParam(JPEG_ALLOW_JPEG_EMBEDDING, allowJpegEmbedding);
  287. }
  288. private void createResourceGroupFile() throws FOPException {
  289. try {
  290. Configuration resourceGroupUriCfg = cfg.getChild(RESOURCE_GROUP_URI.getName(), false);
  291. if (resourceGroupUriCfg != null) {
  292. URI resourceGroupUri = InternalResourceResolver.cleanURI(resourceGroupUriCfg.getValue());
  293. setParam(RESOURCE_GROUP_URI, resourceGroupUri);
  294. }
  295. } catch (ConfigurationException e) {
  296. LogUtil.handleException(LOG, e, strict);
  297. } catch (URISyntaxException use) {
  298. LogUtil.handleException(LOG, use, strict);
  299. }
  300. }
  301. private void createResourceLevel() throws FOPException {
  302. Configuration defaultResourceLevelCfg = cfg.getChild(DEFAULT_RESOURCE_LEVELS.getName(), false);
  303. if (defaultResourceLevelCfg != null) {
  304. AFPResourceLevelDefaults defaults = new AFPResourceLevelDefaults();
  305. String[] types = defaultResourceLevelCfg.getAttributeNames();
  306. for (String type : types) {
  307. try {
  308. String level = defaultResourceLevelCfg.getAttribute(type);
  309. defaults.setDefaultResourceLevel(type, AFPResourceLevel.valueOf(level));
  310. } catch (IllegalArgumentException iae) {
  311. LogUtil.handleException(LOG, iae, strict);
  312. } catch (ConfigurationException e) {
  313. LogUtil.handleException(LOG, e, strict);
  314. }
  315. }
  316. setParam(DEFAULT_RESOURCE_LEVELS, defaults);
  317. }
  318. }
  319. }
  320. }