From 8c3aa5ee7fae54a61a0481f663281fe9e9518f82 Mon Sep 17 00:00:00 2001 From: Jeremias Maerki Date: Fri, 22 Apr 2011 07:15:43 +0000 Subject: [PATCH] Added option for PostScript output to optimize for file size rather than quality. Fixed some missing PostScript command mappings. git-svn-id: https://svn.apache.org/repos/asf/xmlgraphics/fop/trunk@1095878 13f79535-47bb-0310-9956-ffa450edef68 --- .../content/xdocs/trunk/output.xml | 7 +++++ .../intermediate/AbstractIFPainter.java | 27 ++++++++++++++++ .../apache/fop/render/ps/PSBorderPainter.java | 17 +++++----- .../org/apache/fop/render/ps/PSPainter.java | 15 ++++++--- .../fop/render/ps/PSRendererConfigurator.java | 5 +++ .../apache/fop/render/ps/PSRenderingMode.java | 31 +++++++++++++++++++ .../apache/fop/render/ps/PSRenderingUtil.java | 20 ++++++++++++ 7 files changed, 110 insertions(+), 12 deletions(-) create mode 100644 src/java/org/apache/fop/render/ps/PSRenderingMode.java diff --git a/src/documentation/content/xdocs/trunk/output.xml b/src/documentation/content/xdocs/trunk/output.xml index c174bf2b5..bc4d87088 100644 --- a/src/documentation/content/xdocs/trunk/output.xml +++ b/src/documentation/content/xdocs/trunk/output.xml @@ -287,6 +287,7 @@ out = proc.getOutputStream();]]> false false true + quality ]]>

The default value for the "auto-rotate-landscape" setting is "false". Setting it @@ -319,6 +320,12 @@ out = proc.getOutputStream();]]> the particular postscript implementation issuing unwanted postscript subsystem initgraphics/erasepage calls on each setpagedevice call.

+

+ The default value for the "rendering" setting is "quality". Setting it to "size" + optimizes rendering for smaller file sizes which can involve minor compromises in + rendering quality. For example, solid borders are then painted as plain rectangles + instead of the elaborate painting instructions required for mixed-color borders. +

Limitations diff --git a/src/java/org/apache/fop/render/intermediate/AbstractIFPainter.java b/src/java/org/apache/fop/render/intermediate/AbstractIFPainter.java index 1b870a7c5..2226274ab 100644 --- a/src/java/org/apache/fop/render/intermediate/AbstractIFPainter.java +++ b/src/java/org/apache/fop/render/intermediate/AbstractIFPainter.java @@ -46,6 +46,7 @@ import org.apache.xmlgraphics.image.loader.util.ImageUtil; import org.apache.fop.ResourceEventProducer; import org.apache.fop.apps.FOUserAgent; import org.apache.fop.apps.FopFactory; +import org.apache.fop.fo.Constants; import org.apache.fop.render.ImageHandler; import org.apache.fop.render.ImageHandlerRegistry; import org.apache.fop.render.ImageHandlerUtil; @@ -342,6 +343,32 @@ public abstract class AbstractIFPainter implements IFPainter { } } + /** + * Indicates whether the given border segments (if present) have only solid borders, i.e. + * could be painted in a simplified fashion keeping the output file smaller. + * @param before the border segment on the before-side (top) + * @param after the border segment on the after-side (bottom) + * @param start the border segment on the start-side (left) + * @param end the border segment on the end-side (right) + * @return true if any border segment has a non-solid border style + */ + protected boolean hasOnlySolidBorders(BorderProps before, BorderProps after, + BorderProps start, BorderProps end) { + if (before != null && before.style != Constants.EN_SOLID) { + return false; + } + if (after != null && after.style != Constants.EN_SOLID) { + return false; + } + if (start != null && start.style != Constants.EN_SOLID) { + return false; + } + if (end != null && end.style != Constants.EN_SOLID) { + return false; + } + return true; + } + /** {@inheritDoc} */ public void drawLine(Point start, Point end, int width, Color color, RuleStyle style) throws IFException { diff --git a/src/java/org/apache/fop/render/ps/PSBorderPainter.java b/src/java/org/apache/fop/render/ps/PSBorderPainter.java index 1e2964eed..a52974d36 100644 --- a/src/java/org/apache/fop/render/ps/PSBorderPainter.java +++ b/src/java/org/apache/fop/render/ps/PSBorderPainter.java @@ -62,9 +62,10 @@ public class PSBorderPainter extends BorderPainter { private static void drawLine(PSGenerator gen, float startx, float starty, float endx, float endy) throws IOException { gen.writeln(gen.formatDouble(startx) + " " - + gen.formatDouble(starty) + " M " + + gen.formatDouble(starty) + " " + gen.mapCommand("moveto") + " " + gen.formatDouble(endx) + " " - + gen.formatDouble(endy) + " lineto stroke newpath"); + + gen.formatDouble(endy) + " " + gen.mapCommand("lineto") + " " + + gen.mapCommand("stroke") + " " + gen.mapCommand("newpath")); } /** @@ -260,7 +261,8 @@ public class PSBorderPainter extends BorderPainter { lineTo(end.x, starty + 2 * half); lineTo(start.x, starty + 2 * half); closePath(); - generator.writeln(" fill newpath"); + generator.write(" " + generator.mapCommand("fill")); + generator.writeln(" " + generator.mapCommand("newpath")); generator.useColor(color); if (style == RuleStyle.GROOVE) { moveTo(start.x, starty); @@ -276,7 +278,8 @@ public class PSBorderPainter extends BorderPainter { lineTo(end.x - half, starty + half); } closePath(); - generator.writeln(" fill newpath"); + generator.write(" " + generator.mapCommand("fill")); + generator.writeln(" " + generator.mapCommand("newpath")); break; default: throw new UnsupportedOperationException("rule style not supported"); @@ -293,13 +296,13 @@ public class PSBorderPainter extends BorderPainter { /** {@inheritDoc} */ protected void moveTo(int x, int y) throws IOException { generator.writeln(generator.formatDouble(toPoints(x)) + " " - + generator.formatDouble(toPoints(y)) + " M"); + + generator.formatDouble(toPoints(y)) + " " + generator.mapCommand("moveto")); } /** {@inheritDoc} */ protected void lineTo(int x, int y) throws IOException { generator.writeln(generator.formatDouble(toPoints(x)) + " " - + generator.formatDouble(toPoints(y)) + " lineto"); + + generator.formatDouble(toPoints(y)) + " " + generator.mapCommand("lineto")); } /** {@inheritDoc} */ @@ -314,7 +317,7 @@ public class PSBorderPainter extends BorderPainter { /** {@inheritDoc} */ protected void clip() throws IOException { - generator.writeln("clip newpath"); + generator.writeln(generator.mapCommand("clip") + " " + generator.mapCommand("newpath")); } /** {@inheritDoc} */ diff --git a/src/java/org/apache/fop/render/ps/PSPainter.java b/src/java/org/apache/fop/render/ps/PSPainter.java index b8a6d40f6..1b1f9437d 100644 --- a/src/java/org/apache/fop/render/ps/PSPainter.java +++ b/src/java/org/apache/fop/render/ps/PSPainter.java @@ -202,7 +202,7 @@ public class PSPainter extends AbstractIFPainter { endTextObject(); generator.defineRect(rect.x / 1000.0, rect.y / 1000.0, rect.width / 1000.0, rect.height / 1000.0); - generator.writeln("clip newpath"); + generator.writeln(generator.mapCommand("clip") + " " + generator.mapCommand("newpath")); } catch (IOException ioe) { throw new IFException("I/O error in clipRect()", ioe); } @@ -226,7 +226,7 @@ public class PSPainter extends AbstractIFPainter { } generator.defineRect(rect.x / 1000.0, rect.y / 1000.0, rect.width / 1000.0, rect.height / 1000.0); - generator.writeln("fill"); + generator.writeln(generator.mapCommand("fill")); } catch (IOException ioe) { throw new IFException("I/O error in fillRect()", ioe); } @@ -239,7 +239,12 @@ public class PSPainter extends AbstractIFPainter { if (before != null || after != null || start != null || end != null) { try { endTextObject(); - this.borderPainter.drawBorders(rect, before, after, start, end); + if (getPSUtil().getRenderingMode() == PSRenderingMode.SIZE + && hasOnlySolidBorders(before, after, start, end)) { + super.drawBorderRect(rect, before, after, start, end); + } else { + this.borderPainter.drawBorders(rect, before, after, start, end); + } } catch (IOException ioe) { throw new IFException("I/O error in drawBorderRect()", ioe); } @@ -478,9 +483,9 @@ public class PSPainter extends AbstractIFPainter { spb.append(formatMptAsPt(generator, letterSpacing)) .append(" 0 "); sb.insert(0, spb.toString()); - sb.append(" ashow"); + sb.append(" " + generator.mapCommand("ashow")); } else { - sb.append(" show"); + sb.append(" " + generator.mapCommand("show")); } } generator.writeln(sb.toString()); diff --git a/src/java/org/apache/fop/render/ps/PSRendererConfigurator.java b/src/java/org/apache/fop/render/ps/PSRendererConfigurator.java index 2280bf0dc..68f7e9d62 100644 --- a/src/java/org/apache/fop/render/ps/PSRendererConfigurator.java +++ b/src/java/org/apache/fop/render/ps/PSRendererConfigurator.java @@ -66,6 +66,11 @@ public class PSRendererConfigurator extends PrintRendererConfigurator if (child != null) { psUtil.setOptimizeResources(child.getValueAsBoolean(false)); } + child = cfg.getChild("rendering"); + if (child != null) { + psUtil.setRenderingMode(PSRenderingMode.valueOf( + child.getValue(psUtil.getRenderingMode().toString()).toUpperCase())); + } psUtil.setSafeSetPageDevice( cfg.getChild("safe-set-page-device").getValueAsBoolean(false)); psUtil.setDSCComplianceEnabled( diff --git a/src/java/org/apache/fop/render/ps/PSRenderingMode.java b/src/java/org/apache/fop/render/ps/PSRenderingMode.java new file mode 100644 index 000000000..dc48b56ac --- /dev/null +++ b/src/java/org/apache/fop/render/ps/PSRenderingMode.java @@ -0,0 +1,31 @@ +/* + * 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.ps; + +/** + * Enumeration that specifies the rendering mode for PostScript output. {@link #SIZE} tries + * to produce smaller files at the expense of quality, whereas {@link #QUALITY} tries to + * produce the best possible quality. + */ +enum PSRenderingMode { + + SIZE, QUALITY; + +} diff --git a/src/java/org/apache/fop/render/ps/PSRenderingUtil.java b/src/java/org/apache/fop/render/ps/PSRenderingUtil.java index d7890d144..b22391718 100644 --- a/src/java/org/apache/fop/render/ps/PSRenderingUtil.java +++ b/src/java/org/apache/fop/render/ps/PSRenderingUtil.java @@ -56,6 +56,12 @@ public class PSRenderingUtil implements PSConfigurationConstants { /** Determines whether the PS file is generated in two passes to minimize file size */ private boolean optimizeResources = false; + /** + * Determines whether the generated PostScript code is optimized for minimum file size + * of best quality. + */ + private PSRenderingMode renderingMode = PSRenderingMode.QUALITY; + PSRenderingUtil(FOUserAgent userAgent) { this.userAgent = userAgent; initialize(); @@ -287,5 +293,19 @@ public class PSRenderingUtil implements PSConfigurationConstants { return optimizeResources; } + /** + * Sets the rendering mode. + * @param renderingMode the rendering mode + */ + public void setRenderingMode(PSRenderingMode renderingMode) { + this.renderingMode = renderingMode; + } + /** + * Returns the rendering mode. + * @return the rendering mode + */ + public PSRenderingMode getRenderingMode() { + return this.renderingMode; + } } -- 2.39.5