您最多选择25个主题 主题必须以字母或数字开头,可以包含连字符 (-),并且长度不得超过35个字符

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