diff options
Diffstat (limited to 'src/java/org/apache/fop/render/afp/AFPRendererConfig.java')
-rw-r--r-- | src/java/org/apache/fop/render/afp/AFPRendererConfig.java | 375 |
1 files changed, 375 insertions, 0 deletions
diff --git a/src/java/org/apache/fop/render/afp/AFPRendererConfig.java b/src/java/org/apache/fop/render/afp/AFPRendererConfig.java new file mode 100644 index 000000000..90cc6e767 --- /dev/null +++ b/src/java/org/apache/fop/render/afp/AFPRendererConfig.java @@ -0,0 +1,375 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The ASF licenses this file to You under the Apache License, Version 2.0 + * (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +/* $Id$ */ + +package org.apache.fop.render.afp; + +import java.net.URI; +import java.net.URISyntaxException; +import java.util.EnumMap; + +import org.apache.avalon.framework.configuration.Configuration; +import org.apache.avalon.framework.configuration.ConfigurationException; +import org.apache.commons.logging.Log; +import org.apache.commons.logging.LogFactory; + +import org.apache.fop.afp.AFPConstants; +import org.apache.fop.afp.AFPDataObjectInfo; +import org.apache.fop.afp.AFPEventProducer; +import org.apache.fop.afp.AFPResourceLevel; +import org.apache.fop.afp.AFPResourceLevelDefaults; +import org.apache.fop.afp.modca.triplets.MappingOptionTriplet; +import org.apache.fop.apps.FOPException; +import org.apache.fop.apps.FOUserAgent; +import org.apache.fop.apps.MimeConstants; +import org.apache.fop.apps.io.InternalResourceResolver; +import org.apache.fop.fonts.FontManager; +import org.apache.fop.render.RendererConfig; +import org.apache.fop.render.afp.AFPFontConfig.AFPFontInfoConfigParser; +import org.apache.fop.util.LogUtil; + +import static org.apache.fop.render.afp.AFPRendererConfig.ImagesModeOptions.MODE_COLOR; +import static org.apache.fop.render.afp.AFPRendererConfig.ImagesModeOptions.MODE_GRAYSCALE; +import static org.apache.fop.render.afp.AFPRendererOption.DEFAULT_RESOURCE_LEVELS; +import static org.apache.fop.render.afp.AFPRendererOption.GOCA; +import static org.apache.fop.render.afp.AFPRendererOption.GOCA_TEXT; +import static org.apache.fop.render.afp.AFPRendererOption.IMAGES; +import static org.apache.fop.render.afp.AFPRendererOption.IMAGES_DITHERING_QUALITY; +import static org.apache.fop.render.afp.AFPRendererOption.IMAGES_FS45; +import static org.apache.fop.render.afp.AFPRendererOption.IMAGES_JPEG; +import static org.apache.fop.render.afp.AFPRendererOption.IMAGES_MAPPING_OPTION; +import static org.apache.fop.render.afp.AFPRendererOption.IMAGES_MODE; +import static org.apache.fop.render.afp.AFPRendererOption.IMAGES_NATIVE; +import static org.apache.fop.render.afp.AFPRendererOption.IMAGES_WRAP_PSEG; +import static org.apache.fop.render.afp.AFPRendererOption.JPEG_ALLOW_JPEG_EMBEDDING; +import static org.apache.fop.render.afp.AFPRendererOption.JPEG_BITMAP_ENCODING_QUALITY; +import static org.apache.fop.render.afp.AFPRendererOption.LINE_WIDTH_CORRECTION; +import static org.apache.fop.render.afp.AFPRendererOption.RENDERER_RESOLUTION; +import static org.apache.fop.render.afp.AFPRendererOption.RESOURCE_GROUP_URI; +import static org.apache.fop.render.afp.AFPRendererOption.SHADING; + +/** + * The AFP renderer config object. + */ +public final class AFPRendererConfig implements RendererConfig { + + /** + * An enumeration for the various images modes available to the AFP renderer. + */ + public enum ImagesModeOptions { + + MODE_GRAYSCALE("b+w", "bits-per-pixel"), + MODE_COLOR("color", "cmyk"); + + private final String name; + + private final String modeAttribute; + + private ImagesModeOptions(String name, String modeAttribute) { + this.name = name; + this.modeAttribute = modeAttribute; + } + + public String getName() { + return name; + } + + public String getModeAttribute() { + return modeAttribute; + } + + public static ImagesModeOptions forName(String name) { + for (ImagesModeOptions option : values()) { + if (option.name.equals(name)) { + return option; + } + } + throw new IllegalArgumentException(name); + } + } + + private final EnumMap<AFPRendererOption, Object> params = new EnumMap<AFPRendererOption, Object>(AFPRendererOption.class); + + private final EnumMap<ImagesModeOptions, Object> imageModeParams + = new EnumMap<ImagesModeOptions, Object>(ImagesModeOptions.class); + + private final AFPFontConfig fontConfig; + + private AFPRendererConfig(AFPFontConfig fontConfig) { + this.fontConfig = fontConfig; + } + + public AFPFontConfig getFontInfoConfig() { + return fontConfig; + } + + public Boolean isColorImages() { + return getParam(IMAGES_MODE, Boolean.class); + } + + public Boolean isCmykImagesSupported() { + if (!isColorImages()) { + throw new IllegalStateException(); + } + return Boolean.class.cast(imageModeParams.get(MODE_COLOR)); + } + + public Integer getBitsPerPixel() { + if (isColorImages()) { + throw new IllegalStateException(); + } + return Integer.class.cast(imageModeParams.get(MODE_GRAYSCALE)); + } + + public Float getDitheringQuality() { + return getParam(IMAGES_DITHERING_QUALITY, Float.class); + } + + public Boolean isNativeImagesSupported() { + return getParam(IMAGES_NATIVE, Boolean.class); + } + + public AFPShadingMode getShadingMode() { + return getParam(SHADING, AFPShadingMode.class); + } + + public Integer getResolution() { + return getParam(RENDERER_RESOLUTION, Integer.class); + } + + + public URI getDefaultResourceGroupUri() { + return getParam(RESOURCE_GROUP_URI, URI.class); + } + + public AFPResourceLevelDefaults getResourceLevelDefaults() { + return getParam(DEFAULT_RESOURCE_LEVELS, AFPResourceLevelDefaults.class); + } + + public Boolean isWrapPseg() { + return getParam(IMAGES_WRAP_PSEG, Boolean.class); + } + + public Boolean isFs45() { + return getParam(IMAGES_FS45, Boolean.class); + } + + public Boolean allowJpegEmbedding() { + return getParam(JPEG_ALLOW_JPEG_EMBEDDING, Boolean.class); + } + + public Float getBitmapEncodingQuality() { + return getParam(JPEG_BITMAP_ENCODING_QUALITY, Float.class); + } + + public Float getLineWidthCorrection() { + return getParam(LINE_WIDTH_CORRECTION, Float.class); + } + + public Boolean isGocaEnabled() { + return getParam(GOCA, Boolean.class); + } + + public Boolean isStrokeGocaText() { + return getParam(GOCA_TEXT, Boolean.class); + } + + private <T> T getParam(AFPRendererOption options, Class<T> type) { + assert options.getType().equals(type); + return type.cast(params.get(options)); + } + + private <T> void setParam(AFPRendererOption option, T value) { + assert option.getType().isInstance(value); + params.put(option, value); + } + + /** + * The parser for AFP renderer specific data in the FOP conf. + */ + public static final class AFPRendererConfigParser implements RendererConfigParser { + + private static final Log LOG = LogFactory.getLog(AFPRendererConfigParser.class); + + /** {@inheritDoc} */ + public AFPRendererConfig build(FOUserAgent userAgent, Configuration cfg) throws FOPException { + boolean strict = userAgent.validateUserConfigStrictly(); + AFPRendererConfig config = null; + AFPEventProducer eventProducer = AFPEventProducer.Provider.get(userAgent.getEventBroadcaster()); + try { + config = new ParserHelper(cfg, userAgent.getFontManager(), strict, eventProducer).config; + } catch (ConfigurationException e) { + LogUtil.handleException(LOG, e, strict); + } + return config; + } + + /** {@inheritDoc} */ + public String getMimeType() { + return MimeConstants.MIME_AFP; + } + } + + private static final class ParserHelper { + + private static final Log LOG = LogFactory.getLog(ParserHelper.class); + + private final AFPRendererConfig config; + + private final boolean strict; + + private final Configuration cfg; + + private ParserHelper(Configuration cfg, FontManager fontManager, boolean strict, + AFPEventProducer eventProducer) + throws ConfigurationException, FOPException { + this.cfg = cfg; + this.strict = strict; + if (cfg != null) { + config = new AFPRendererConfig(new AFPFontInfoConfigParser().parse(cfg, + fontManager, strict, eventProducer)); + configure(); + } else { + config = new AFPRendererConfig(new AFPFontInfoConfigParser().getEmptyConfig()); + } + } + + private void configure() throws ConfigurationException, FOPException { + configureImages(); + setParam(SHADING, AFPShadingMode.getValueOf( + cfg.getChild(SHADING.getName()).getValue(AFPShadingMode.COLOR.getName()))); + Configuration rendererResolutionCfg = cfg.getChild(RENDERER_RESOLUTION.getName(), false); + setParam(RENDERER_RESOLUTION, rendererResolutionCfg == null ? 240 + : rendererResolutionCfg.getValueAsInteger(240)); + Configuration lineWidthCorrectionCfg = cfg.getChild(LINE_WIDTH_CORRECTION.getName(), + false); + setParam(LINE_WIDTH_CORRECTION, lineWidthCorrectionCfg != null + ? lineWidthCorrectionCfg.getValueAsFloat() + : AFPConstants.LINE_WIDTH_CORRECTION); + Configuration gocaCfg = cfg.getChild(GOCA.getName()); + boolean gocaEnabled = gocaCfg.getAttributeAsBoolean("enabled", true); + setParam(GOCA, gocaEnabled); + String strokeGocaText = gocaCfg.getAttribute(GOCA_TEXT.getName(), "default"); + setParam(GOCA_TEXT, "stroke".equalsIgnoreCase(strokeGocaText) + || "shapes".equalsIgnoreCase(strokeGocaText)); + //TODO remove + createResourceGroupFile(); + createResourceLevel(); + } + + private void setParam(AFPRendererOption option, Object value) { + config.setParam(option, value); + } + + private void configureImages() throws ConfigurationException, FOPException { + Configuration imagesCfg = cfg.getChild(IMAGES.getName()); + ImagesModeOptions imagesMode = ImagesModeOptions.forName(imagesCfg.getAttribute( + IMAGES_MODE.getName(), MODE_GRAYSCALE.getName())); + boolean colorImages = MODE_COLOR == imagesMode; + setParam(IMAGES_MODE, colorImages); + if (colorImages) { + config.imageModeParams.put(MODE_COLOR, imagesCfg + .getAttributeAsBoolean(imagesMode.getModeAttribute(), false)); + } else { + config.imageModeParams.put(MODE_GRAYSCALE, + imagesCfg.getAttributeAsInteger(imagesMode.getModeAttribute(), 8)); + } + String dithering = imagesCfg.getAttribute(AFPRendererOption.IMAGES_DITHERING_QUALITY.getName(), "medium"); + float dq; + if (dithering.startsWith("min")) { + dq = 0.0f; + } else if (dithering.startsWith("max")) { + dq = 1.0f; + } else { + try { + dq = Float.parseFloat(dithering); + } catch (NumberFormatException nfe) { + //Default value + dq = 0.5f; + } + } + setParam(IMAGES_DITHERING_QUALITY, dq); + setParam(IMAGES_NATIVE, imagesCfg.getAttributeAsBoolean(IMAGES_NATIVE.getName(), false)); + setParam(IMAGES_WRAP_PSEG, + imagesCfg.getAttributeAsBoolean(IMAGES_WRAP_PSEG.getName(), false)); + setParam(IMAGES_FS45, imagesCfg.getAttributeAsBoolean(IMAGES_FS45.getName(), false)); + if ("scale-to-fit".equals(imagesCfg.getAttribute(IMAGES_MAPPING_OPTION.getName(), null))) { + setParam(IMAGES_MAPPING_OPTION, MappingOptionTriplet.SCALE_TO_FILL); + } else { + setParam(IMAGES_MAPPING_OPTION, AFPDataObjectInfo.DEFAULT_MAPPING_OPTION); + } + configureJpegImages(imagesCfg); + } + + private void configureJpegImages(Configuration imagesCfg) { + Configuration jpegConfig = imagesCfg.getChild(IMAGES_JPEG.getName()); + float bitmapEncodingQuality = 1.0f; + boolean allowJpegEmbedding = false; + if (jpegConfig != null) { + allowJpegEmbedding = jpegConfig.getAttributeAsBoolean( + JPEG_ALLOW_JPEG_EMBEDDING.getName(), + false); + String bitmapEncodingQualityStr = jpegConfig.getAttribute( + JPEG_BITMAP_ENCODING_QUALITY.getName(), null); + if (bitmapEncodingQualityStr != null) { + try { + bitmapEncodingQuality = Float.parseFloat(bitmapEncodingQualityStr); + } catch (NumberFormatException nfe) { + //ignore and leave the default above + } + } + } + setParam(JPEG_BITMAP_ENCODING_QUALITY, bitmapEncodingQuality); + setParam(JPEG_ALLOW_JPEG_EMBEDDING, allowJpegEmbedding); + } + + private void createResourceGroupFile() throws FOPException { + try { + Configuration resourceGroupUriCfg = cfg.getChild(RESOURCE_GROUP_URI.getName(), false); + if (resourceGroupUriCfg != null) { + URI resourceGroupUri = InternalResourceResolver.cleanURI(resourceGroupUriCfg.getValue()); + setParam(RESOURCE_GROUP_URI, resourceGroupUri); + } + } catch (ConfigurationException e) { + LogUtil.handleException(LOG, e, strict); + } catch (URISyntaxException use) { + LogUtil.handleException(LOG, use, strict); + } + } + + private void createResourceLevel() throws FOPException { + Configuration defaultResourceLevelCfg = cfg.getChild(DEFAULT_RESOURCE_LEVELS.getName(), false); + if (defaultResourceLevelCfg != null) { + AFPResourceLevelDefaults defaults = new AFPResourceLevelDefaults(); + String[] types = defaultResourceLevelCfg.getAttributeNames(); + for (int i = 0, c = types.length; i < c; i++) { + String type = types[i]; + try { + String level = defaultResourceLevelCfg.getAttribute(type); + defaults.setDefaultResourceLevel(type, AFPResourceLevel.valueOf(level)); + } catch (IllegalArgumentException iae) { + LogUtil.handleException(LOG, iae, strict); + } catch (ConfigurationException e) { + LogUtil.handleException(LOG, e, strict); + } + } + setParam(DEFAULT_RESOURCE_LEVELS, defaults); + } + } + } +} |