From ccb0ccb674eb0cdd014a0ca236403a640bb57fdf Mon Sep 17 00:00:00 2001 From: Adrian Cumiskey Date: Mon, 7 Jul 2008 12:48:50 +0000 Subject: [PATCH] Merged revisions 674245,674267,674269,674272-674273,674276,674325,674468,674470-674471 via svnmerge from https://svn.apache.org/repos/asf/xmlgraphics/fop/trunk ........ r674245 | adelmelle | 2008-07-05 23:53:58 +0100 (Sat, 05 Jul 2008) | 1 line Fixed ClassCastException when specifying column-number on something other than a fo:table-column or fo:table-cell... ........ r674267 | adelmelle | 2008-07-06 08:50:23 +0100 (Sun, 06 Jul 2008) | 1 line Switch AreaTreeParser to use a java.nio.CharBuffer, and ignore characters events for all elements other than , or ........ r674269 | adelmelle | 2008-07-06 09:15:50 +0100 (Sun, 06 Jul 2008) | 1 line Remove deprecated Character area class ........ r674272 | adelmelle | 2008-07-06 09:44:54 +0100 (Sun, 06 Jul 2008) | 1 line Redo changes made in r674056... ........ r674273 | adelmelle | 2008-07-06 09:46:50 +0100 (Sun, 06 Jul 2008) | 1 line Simplified implementation of Area.getTraitAsBoolean() ........ r674276 | adelmelle | 2008-07-06 10:17:14 +0100 (Sun, 06 Jul 2008) | 3 lines Extracted conversion methods for String to int[] or double[] to a utility class. Made AreaTreeParser.getAttributeAsXXX() methods static to stress their utility character, and removed the private parseRect() in favor of getAttributeAsRectangle2D(). ........ r674325 | adelmelle | 2008-07-06 19:19:48 +0100 (Sun, 06 Jul 2008) | 1 line Fixed error; inadvertently switched the condition with r674272... ........ r674468 | acumiskey | 2008-07-07 13:36:57 +0100 (Mon, 07 Jul 2008) | 1 line Possible NullPointerException avoided ........ r674470 | acumiskey | 2008-07-07 13:38:04 +0100 (Mon, 07 Jul 2008) | 1 line Added new set accessor method for EncryptionParams. ........ r674471 | acumiskey | 2008-07-07 13:42:12 +0100 (Mon, 07 Jul 2008) | 1 line Added PDF encryption parameter support in configuration. ........ git-svn-id: https://svn.apache.org/repos/asf/xmlgraphics/fop/branches/Temp_AFPGOCAResources@674476 13f79535-47bb-0310-9956-ffa450edef68 --- .../content/xdocs/trunk/configuration.xml | 21 +++ src/java/org/apache/fop/area/Area.java | 8 +- .../org/apache/fop/area/AreaTreeParser.java | 169 ++++++++---------- .../org/apache/fop/area/inline/Character.java | 62 ------- .../apache/fop/fo/flow/table/TableFObj.java | 114 +++++++----- src/java/org/apache/fop/pdf/PDFDocument.java | 6 +- .../apache/fop/render/AbstractRenderer.java | 22 +-- .../apache/fop/render/pdf/PDFRenderer.java | 8 + .../render/pdf/PDFRendererConfigurator.java | 48 ++++- .../org/apache/fop/util/ConversionUtils.java | 110 ++++++++++++ status.xml | 3 + 11 files changed, 339 insertions(+), 232 deletions(-) delete mode 100644 src/java/org/apache/fop/area/inline/Character.java create mode 100644 src/java/org/apache/fop/util/ConversionUtils.java diff --git a/src/documentation/content/xdocs/trunk/configuration.xml b/src/documentation/content/xdocs/trunk/configuration.xml index e27ae94df..81b4d40ac 100644 --- a/src/documentation/content/xdocs/trunk/configuration.xml +++ b/src/documentation/content/xdocs/trunk/configuration.xml @@ -294,6 +294,27 @@ ]]> + +

FOP supports encryption of PDF output, thanks to Patrick C. Lankswert. + This feature is commonly used to prevent unauthorized viewing, printing, editing, copying text + from the document and doing annotations. It is also possible to ask the user for a password in + order to view the contents. Note that there already exist third party applications which can + decrypt an encrypted PDF without effort and allow the aforementioned operations, therefore the + degree of protection is limited. For further information about features and restrictions + regarding PDF encryption, look at the documentation coming with Adobe Acrobat or the technical + documentation on the Adobe web site.

+ + + testuserpass + testownerpass + + + + + + ]]> +
Special Settings for the PostScript Renderer diff --git a/src/java/org/apache/fop/area/Area.java b/src/java/org/apache/fop/area/Area.java index 9c0fc8db6..ab9590685 100644 --- a/src/java/org/apache/fop/area/Area.java +++ b/src/java/org/apache/fop/area/Area.java @@ -417,17 +417,11 @@ public class Area extends AreaTreeObject implements Serializable { /** * Get a boolean trait from this area. - * * @param oTraitCode the trait key * @return the trait value */ public boolean getTraitAsBoolean(Object oTraitCode) { - final Object obj = getTrait(oTraitCode); - if (obj instanceof Boolean) { - return ((Boolean)obj).booleanValue(); - } else { - return false; - } + return Boolean.TRUE.equals(getTrait(oTraitCode)); } /** diff --git a/src/java/org/apache/fop/area/AreaTreeParser.java b/src/java/org/apache/fop/area/AreaTreeParser.java index d48221c0a..6d9fd4f32 100644 --- a/src/java/org/apache/fop/area/AreaTreeParser.java +++ b/src/java/org/apache/fop/area/AreaTreeParser.java @@ -26,6 +26,7 @@ import java.util.Map; import java.util.Set; import java.util.Stack; import java.util.StringTokenizer; +import java.nio.CharBuffer; import javax.xml.transform.Source; import javax.xml.transform.Transformer; @@ -56,7 +57,6 @@ import org.apache.fop.apps.FOUserAgent; import org.apache.fop.area.Trait.Background; import org.apache.fop.area.Trait.InternalLink; import org.apache.fop.area.inline.AbstractTextArea; -import org.apache.fop.area.inline.Character; import org.apache.fop.area.inline.ForeignObject; import org.apache.fop.area.inline.Image; import org.apache.fop.area.inline.InlineArea; @@ -78,6 +78,7 @@ import org.apache.fop.traits.BorderProps; import org.apache.fop.util.ColorUtil; import org.apache.fop.util.ContentHandlerFactory; import org.apache.fop.util.ContentHandlerFactoryRegistry; +import org.apache.fop.util.ConversionUtils; import org.apache.fop.util.DefaultErrorListener; /** @@ -132,8 +133,10 @@ public class AreaTreeParser { private ElementMappingRegistry elementMappingRegistry; private Attributes lastAttributes; - private StringBuffer content = new StringBuffer(); + private CharBuffer content = CharBuffer.allocate(64); + private boolean ignoreCharacters = true; + private PageViewport currentPageViewport; private Map pageViewportsByKey = new java.util.HashMap(); // set of "ID firsts" that have already been assigned to a PV: @@ -176,7 +179,6 @@ public class AreaTreeParser { makers.put("text", new TextMaker()); makers.put("word", new WordMaker()); makers.put("space", new SpaceMaker()); - makers.put("char", new CharMaker()); makers.put("leader", new LeaderMaker()); makers.put("viewport", new ViewportMaker()); makers.put("image", new ImageMaker()); @@ -186,15 +188,6 @@ public class AreaTreeParser { makers.put("destination", new DestinationMaker()); } - private static Rectangle2D parseRect(String rect) { - StringTokenizer tokenizer = new StringTokenizer(rect, " "); - return new Rectangle2D.Double( - Double.parseDouble(tokenizer.nextToken()), - Double.parseDouble(tokenizer.nextToken()), - Double.parseDouble(tokenizer.nextToken()), - Double.parseDouble(tokenizer.nextToken())); - } - private Area findAreaType(Class clazz) { if (areaStack.size() > 0) { int pos = areaStack.size() - 1; @@ -261,7 +254,10 @@ public class AreaTreeParser { boolean handled = true; if ("".equals(uri)) { Maker maker = (Maker)makers.get(localName); + content.clear(); + ignoreCharacters = true; if (maker != null) { + ignoreCharacters = maker.ignoreCharacters(); maker.startElement(attributes); } else if ("extension-attachments".equals(localName)) { //TODO implement me @@ -311,11 +307,12 @@ public class AreaTreeParser { Maker maker = (Maker)makers.get(localName); if (maker != null) { maker.endElement(); + content.clear(); } + ignoreCharacters = true; } else { //log.debug("Ignoring " + localName + " in namespace: " + uri); } - content.setLength(0); //Reset text buffer (see characters()) } } @@ -324,6 +321,7 @@ public class AreaTreeParser { private static interface Maker { void startElement(Attributes attributes) throws SAXException; void endElement(); + boolean ignoreCharacters(); } private abstract class AbstractMaker implements Maker { @@ -335,6 +333,10 @@ public class AreaTreeParser { public void endElement() { //nop } + + public boolean ignoreCharacters() { + return true; + } } private class AreaTreeMaker extends AbstractMaker { @@ -384,7 +386,7 @@ public class AreaTreeParser { if (currentPageViewport != null) { throw new IllegalStateException("currentPageViewport must be null"); } - Rectangle2D viewArea = parseRect(attributes.getValue("bounds")); + Rectangle2D viewArea = getAttributeAsRectangle2D(attributes, "bounds"); int pageNumber = getAttributeAsInteger(attributes, "nr", -1); String key = attributes.getValue("key"); String pageNumberString = attributes.getValue("formatted-nr"); @@ -420,7 +422,7 @@ public class AreaTreeParser { if (rv != null) { throw new IllegalStateException("Current RegionViewport must be null"); } - Rectangle2D viewArea = parseRect(attributes.getValue("rect")); + Rectangle2D viewArea = getAttributeAsRectangle2D(attributes, "rect"); rv = new RegionViewport(viewArea); transferForeignObjects(attributes, rv); rv.setClip(getAttributeAsBoolean(attributes, "clipped", false)); @@ -444,7 +446,7 @@ public class AreaTreeParser { public void endElement() { assertObjectOfClass(areaStack.pop(), RegionReference.class); - } + } } private class RegionAfterMaker extends AbstractMaker { @@ -455,7 +457,7 @@ public class AreaTreeParser { public void endElement() { assertObjectOfClass(areaStack.pop(), RegionReference.class); - } + } } private class RegionStartMaker extends AbstractMaker { @@ -466,7 +468,7 @@ public class AreaTreeParser { public void endElement() { assertObjectOfClass(areaStack.pop(), RegionReference.class); - } + } } private class RegionEndMaker extends AbstractMaker { @@ -477,7 +479,7 @@ public class AreaTreeParser { public void endElement() { assertObjectOfClass(areaStack.pop(), RegionReference.class); - } + } } private class RegionBodyMaker extends AbstractMaker { @@ -575,7 +577,7 @@ public class AreaTreeParser { public void endElement() { assertObjectOfClass(areaStack.pop(), BeforeFloat.class); - } + } } private class BlockMaker extends AbstractMaker { @@ -627,7 +629,7 @@ public class AreaTreeParser { public void endElement() { assertObjectOfClass(areaStack.pop(), Block.class); - } + } } private class LineAreaMaker extends AbstractMaker { @@ -735,47 +737,37 @@ public class AreaTreeParser { public void endElement() { assertObjectOfClass(areaStack.pop(), TextArea.class); - } + } } private class WordMaker extends AbstractMaker { - private int[] toIntArray(String s) { - if (s == null || s.length() == 0) { - return null; - } - StringTokenizer tokenizer = new StringTokenizer(s, " "); - List values = new java.util.ArrayList(); - while (tokenizer.hasMoreTokens()) { - values.add(new Integer(tokenizer.nextToken())); - } - int[] res = new int[values.size()]; - for (int i = 0, c = res.length; i < c; i++) { - res[i] = ((Integer)values.get(i)).intValue(); - } - return res; - } - public void endElement() { int offset = getAttributeAsInteger(lastAttributes, "offset", 0); - int[] letterAdjust = toIntArray(lastAttributes.getValue("letter-adjust")); - String txt = content.toString(); - WordArea word = new WordArea(txt, offset, letterAdjust); + int[] letterAdjust + = ConversionUtils.toIntArray( + lastAttributes.getValue("letter-adjust"), "\\s"); + content.flip(); + WordArea word = new WordArea(content.toString().trim(), offset, letterAdjust); AbstractTextArea text = getCurrentText(); word.setParentArea(text); text.addChildArea(word); - } + } + + public boolean ignoreCharacters() { + return false; + } } private class SpaceMaker extends AbstractMaker { - + public void endElement() { int offset = getAttributeAsInteger(lastAttributes, "offset", 0); - String txt = content.toString(); //TODO the isAdjustable parameter is currently not used/implemented - if (txt.length() > 0) { + if (content.position() > 0) { + content.flip(); boolean adjustable = getAttributeAsBoolean(lastAttributes, "adj", true); - SpaceArea space = new SpaceArea(txt.charAt(0), offset, adjustable); + SpaceArea space = new SpaceArea(content.charAt(0), offset, adjustable); AbstractTextArea text = getCurrentText(); space.setParentArea(text); text.addChildArea(space); @@ -789,25 +781,11 @@ public class AreaTreeParser { Area parent = (Area)areaStack.peek(); parent.addChildArea(space); } - } - } - - private class CharMaker extends AbstractMaker { - - public void endElement() { - String txt = content.toString(); - Character ch = new Character(txt.charAt(0)); - transferForeignObjects(lastAttributes, ch); - setAreaAttributes(lastAttributes, ch); - setTraits(lastAttributes, ch, SUBSET_COMMON); - setTraits(lastAttributes, ch, SUBSET_BOX); - setTraits(lastAttributes, ch, SUBSET_COLOR); - setTraits(lastAttributes, ch, SUBSET_FONT); - ch.setOffset(getAttributeAsInteger(lastAttributes, "offset", 0)); - ch.setBaselineOffset(getAttributeAsInteger(lastAttributes, "baseline", 0)); - Area parent = (Area)areaStack.peek(); - parent.addChildArea(ch); - } + } + + public boolean ignoreCharacters() { + return false; + } } private class LeaderMaker extends AbstractMaker { @@ -830,9 +808,6 @@ public class AreaTreeParser { Area parent = (Area)areaStack.peek(); parent.addChildArea(leader); } - - public void endElement() { - } } private class ViewportMaker extends AbstractMaker { @@ -854,7 +829,7 @@ public class AreaTreeParser { public void endElement() { assertObjectOfClass(areaStack.pop(), Viewport.class); - } + } } private class ImageMaker extends AbstractMaker { @@ -1097,7 +1072,7 @@ public class AreaTreeParser { } } - private boolean getAttributeAsBoolean(Attributes attributes, String name, + private static boolean getAttributeAsBoolean(Attributes attributes, String name, boolean defaultValue) { String s = attributes.getValue(name); if (s == null) { @@ -1107,7 +1082,7 @@ public class AreaTreeParser { } } - private int getAttributeAsInteger(Attributes attributes, String name, + private static int getAttributeAsInteger(Attributes attributes, String name, int defaultValue) { String s = attributes.getValue(name); if (s == null) { @@ -1117,36 +1092,30 @@ public class AreaTreeParser { } } - private CTM getAttributeAsCTM(Attributes attributes, String name) { + private static CTM getAttributeAsCTM(Attributes attributes, String name) { String s = attributes.getValue(name).trim(); if (s.startsWith("[") && s.endsWith("]")) { s = s.substring(1, s.length() - 1); - StringTokenizer tokenizer = new StringTokenizer(s, " "); - double[] values = new double[] { - Double.parseDouble(tokenizer.nextToken()), - Double.parseDouble(tokenizer.nextToken()), - Double.parseDouble(tokenizer.nextToken()), - Double.parseDouble(tokenizer.nextToken()), - Double.parseDouble(tokenizer.nextToken()), - Double.parseDouble(tokenizer.nextToken())}; + double[] values = ConversionUtils.toDoubleArray(s, "\\s"); + if (values.length != 6) { + throw new IllegalArgumentException("CTM must consist of 6 double values!"); + } return new CTM(values[0], values[1], values[2], values[3], values[4], values[5]); } else { - throw new IllegalArgumentException("CTM must be surrounded by square brackets"); + throw new IllegalArgumentException("CTM must be surrounded by square brackets!"); } } - private Rectangle2D getAttributeAsRectangle2D(Attributes attributes, String name) { + private static Rectangle2D getAttributeAsRectangle2D(Attributes attributes, String name) { String s = attributes.getValue(name).trim(); - StringTokenizer tokenizer = new StringTokenizer(s, " "); - double[] values = new double[] { - Double.parseDouble(tokenizer.nextToken()), - Double.parseDouble(tokenizer.nextToken()), - Double.parseDouble(tokenizer.nextToken()), - Double.parseDouble(tokenizer.nextToken())}; + double[] values = ConversionUtils.toDoubleArray(s, "\\s"); + if (values.length != 4) { + throw new IllegalArgumentException("Rectangle must consist of 4 double values!"); + } return new Rectangle2D.Double(values[0], values[1], values[2], values[3]); } - private void transferForeignObjects(Attributes atts, AreaTreeObject ato) { + private static void transferForeignObjects(Attributes atts, AreaTreeObject ato) { for (int i = 0, c = atts.getLength(); i < c; i++) { String ns = atts.getURI(i); if (ns.length() > 0) { @@ -1163,11 +1132,25 @@ public class AreaTreeParser { public void characters(char[] ch, int start, int length) throws SAXException { if (delegate != null) { delegate.characters(ch, start, length); - } else { - content.append(ch, start, length); + } else if (!ignoreCharacters) { + int maxLength = this.content.capacity() - this.content.position(); + if (maxLength < length) { + // allocate a larger buffer and transfer content + CharBuffer newContent + = CharBuffer.allocate(this.content.position() + length); + this.content.flip(); + newContent.put(this.content); + this.content = newContent; + } + // make sure the full capacity is used + this.content.limit(this.content.capacity()); + // add characters to the buffer + this.content.put(ch, start, length); + // decrease the limit, if necessary + if (this.content.position() < this.content.limit()) { + this.content.limit(this.content.position()); + } } } - } - } diff --git a/src/java/org/apache/fop/area/inline/Character.java b/src/java/org/apache/fop/area/inline/Character.java deleted file mode 100644 index 6b6f9744f..000000000 --- a/src/java/org/apache/fop/area/inline/Character.java +++ /dev/null @@ -1,62 +0,0 @@ -/* - * 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.area.inline; - -/** - * Single character inline area. - * This inline area holds a single character. - * @deprecated A TextArea with a single WordArea as its child should be used instead. - */ -public class Character extends AbstractTextArea { - // use a String instead of a character because if this character - // ends a syllable the hyphenation character must be added - private String character; - - /** - * Create a new character inline area with the given character. - * - * @param ch the character for this inline area - */ - public Character(char ch) { - character = new String() + ch; - } - - /** - * Get the character for this inline character area. - * - * @return the character - */ - public String getChar() { - return character; - } - - /** - * Add the hyphenation character and its length. - * - * @param hyphChar the hyphenation character - * @param hyphSize the size of the hyphenation character - */ - public void addHyphen(char hyphChar, int hyphSize) { - character += hyphChar; - this.setIPD(this.getIPD() + hyphSize); - } - -} - diff --git a/src/java/org/apache/fop/fo/flow/table/TableFObj.java b/src/java/org/apache/fop/fo/flow/table/TableFObj.java index 370bb9de4..faf1f7aba 100644 --- a/src/java/org/apache/fop/fo/flow/table/TableFObj.java +++ b/src/java/org/apache/fop/fo/flow/table/TableFObj.java @@ -55,9 +55,10 @@ public abstract class TableFObj extends FObj { CollapsingBorderModel collapsingBorderModel; /** - * Main constructor + * Create a TableFObj instance that is a child + * of the given {@link FONode} * - * @param parent the parent node + * @param parent the parent {@link FONode} */ public TableFObj(FONode parent) { super(parent); @@ -81,6 +82,8 @@ public abstract class TableFObj extends FObj { } /** + * Return the value for the "border-precedence" property + * for the given side. * * @param side the side for which to return the border precedence * @return the "border-precedence" value for the given side @@ -102,13 +105,13 @@ public abstract class TableFObj extends FObj { /** * Convenience method to returns a reference - * to the base Table instance + * to the base {@link Table} instance. * * @return the base table instance * */ public Table getTable() { - // Will be overridden in Table; for any other Table-node, recursive call to + // Overridden in Table; for any other Table-node, recursive call to // parent.getTable() return ((TableFObj) parent).getTable(); } @@ -119,13 +122,13 @@ public abstract class TableFObj extends FObj { public abstract CommonBorderPaddingBackground getCommonBorderPaddingBackground(); /** - * PropertyMaker subclass for the column-number property - * + * {@link PropertyMaker} subclass for the column-number property */ public static class ColumnNumberPropertyMaker extends PropertyMaker { /** * Constructor + * * @param propId the id of the property for which the maker should * be created */ @@ -144,46 +147,50 @@ public abstract class TableFObj extends FObj { /** + * {@inheritDoc} * Check the value of the column-number property. - * Return the parent's column index (initial value) in case - * of a negative or zero value - * - * @see org.apache.fop.fo.properties.PropertyMaker#make(PropertyList, String, FObj) */ public Property make(PropertyList propertyList, String value, FObj fo) throws PropertyException { + Property p = super.make(propertyList, value, fo); - ColumnNumberManagerHolder parent - = (ColumnNumberManagerHolder) propertyList.getParentFObj(); - ColumnNumberManager columnIndexManager = parent.getColumnNumberManager(); int columnIndex = p.getNumeric().getValue(); int colSpan = propertyList.get(Constants.PR_NUMBER_COLUMNS_SPANNED) .getNumeric().getValue(); - - int lastIndex = columnIndex - 1 + colSpan; - for (int i = columnIndex; i <= lastIndex; ++i) { - if (columnIndexManager.isColumnNumberUsed(i)) { - /* if column-number is already in use by another - * cell/column => error! - */ - TableEventProducer eventProducer = TableEventProducer.Provider.get( - fo.getUserAgent().getEventBroadcaster()); - eventProducer.cellOverlap(this, propertyList.getFObj().getName(), - i, fo.getLocator()); + + // only check whether the column-number is occupied in case it was + // specified on a fo:table-cell or fo:table-column + int foId = propertyList.getFObj().getNameId(); + if (foId == FO_TABLE_COLUMN || foId == FO_TABLE_CELL) { + ColumnNumberManagerHolder parent + = (ColumnNumberManagerHolder) propertyList.getParentFObj(); + ColumnNumberManager columnIndexManager = parent.getColumnNumberManager(); + int lastIndex = columnIndex - 1 + colSpan; + for (int i = columnIndex; i <= lastIndex; ++i) { + if (columnIndexManager.isColumnNumberUsed(i)) { + /* if column-number is already in use by another + * cell/column => error! + */ + TableEventProducer eventProducer + = TableEventProducer.Provider.get( + fo.getUserAgent().getEventBroadcaster()); + eventProducer.cellOverlap( + this, propertyList.getFObj().getName(), + i, propertyList.getFObj().getLocator()); + } } } - return p; } - + /** - * If the value is not positive, return a property whose value is the next column number - * * {@inheritDoc} + * If the value is not positive, return a property whose value + * is the next column number. */ - public Property convertProperty(Property p, - PropertyList propertyList, FObj fo) + public Property convertProperty(Property p, + PropertyList propertyList, FObj fo) throws PropertyException { if (p instanceof EnumProperty) { return EnumNumber.getInstance(p); @@ -191,15 +198,24 @@ public abstract class TableFObj extends FObj { Number val = p.getNumber(); if (val != null) { int i = Math.round(val.floatValue()); + int foId = propertyList.getFObj().getNameId(); if (i <= 0) { - ColumnNumberManagerHolder parent = - (ColumnNumberManagerHolder) propertyList.getParentFObj(); - ColumnNumberManager columnIndexManager = parent.getColumnNumberManager(); - i = columnIndexManager.getCurrentColumnNumber(); + if (foId == FO_TABLE_CELL || foId == FO_TABLE_COLUMN) { + ColumnNumberManagerHolder parent = + (ColumnNumberManagerHolder) propertyList.getParentFObj(); + ColumnNumberManager columnIndexManager = parent.getColumnNumberManager(); + i = columnIndexManager.getCurrentColumnNumber(); + } else { + /* very exceptional case: + * negative column-number specified on + * a FO that is not a fo:table-cell or fo:table-column + */ + i = 1; + } TableEventProducer eventProducer = TableEventProducer.Provider.get(fo.getUserAgent().getEventBroadcaster()); eventProducer.forceNextColumnNumber(this, propertyList.getFObj().getName(), - val, i, fo.getLocator()); + val, i, propertyList.getFObj().getLocator()); } return NumberProperty.getInstance(i); } @@ -233,26 +249,26 @@ public abstract class TableFObj extends FObj { /** * Creates a BorderSpecification from the border set on the given side. If no border * is set, a BorderSpecification with border-style none is created. - * + * * @param side one of CommonBorderPaddingBackground.BEFORE|AFTER|START|END */ private void createBorder(int side) { BorderSpecification borderSpec = new BorderSpecification( getCommonBorderPaddingBackground().getBorderInfo(side), getNameId()); switch (side) { - case CommonBorderPaddingBackground.BEFORE: - borderBefore = new ConditionalBorder(borderSpec, collapsingBorderModel); - break; - case CommonBorderPaddingBackground.AFTER: - borderAfter = new ConditionalBorder(borderSpec, collapsingBorderModel); - break; - case CommonBorderPaddingBackground.START: - borderStart = borderSpec; - break; - case CommonBorderPaddingBackground.END: - borderEnd = borderSpec; - break; - default: assert false; + case CommonBorderPaddingBackground.BEFORE: + borderBefore = new ConditionalBorder(borderSpec, collapsingBorderModel); + break; + case CommonBorderPaddingBackground.AFTER: + borderAfter = new ConditionalBorder(borderSpec, collapsingBorderModel); + break; + case CommonBorderPaddingBackground.START: + borderStart = borderSpec; + break; + case CommonBorderPaddingBackground.END: + borderEnd = borderSpec; + break; + default: assert false; } } } diff --git a/src/java/org/apache/fop/pdf/PDFDocument.java b/src/java/org/apache/fop/pdf/PDFDocument.java index bd44595fb..020a594b4 100644 --- a/src/java/org/apache/fop/pdf/PDFDocument.java +++ b/src/java/org/apache/fop/pdf/PDFDocument.java @@ -528,10 +528,10 @@ public class PDFDocument { public void setEncryption(PDFEncryptionParams params) { getProfile().verifyEncryptionAllowed(); this.encryption = PDFEncryptionManager.newInstance(++this.objectcount, params); - ((PDFObject)this.encryption).setDocument(this); if (encryption != null) { - /**@todo this cast is ugly. PDFObject should be transformed to an interface. */ - addTrailerObject((PDFObject)this.encryption); + PDFObject pdfObject = (PDFObject)encryption; + pdfObject.setDocument(this); + addTrailerObject(pdfObject); } else { log.warn( "PDF encryption is unavailable. PDF will be " diff --git a/src/java/org/apache/fop/render/AbstractRenderer.java b/src/java/org/apache/fop/render/AbstractRenderer.java index 5c3e73ee0..ebff5323b 100644 --- a/src/java/org/apache/fop/render/AbstractRenderer.java +++ b/src/java/org/apache/fop/render/AbstractRenderer.java @@ -54,7 +54,6 @@ import org.apache.fop.area.RegionReference; import org.apache.fop.area.RegionViewport; import org.apache.fop.area.Span; import org.apache.fop.area.Trait; -import org.apache.fop.area.inline.Character; import org.apache.fop.area.inline.Container; import org.apache.fop.area.inline.ForeignObject; import org.apache.fop.area.inline.Image; @@ -405,7 +404,7 @@ public abstract class AbstractRenderer for (int count = 0; count < spans.size(); count++) { span = (Span) spans.get(count); for (int c = 0; c < span.getColumnCount(); c++) { - NormalFlow flow = (NormalFlow) span.getNormalFlow(c); + NormalFlow flow = span.getNormalFlow(c); if (flow != null) { currentBPPosition = saveSpanBPPos; @@ -638,15 +637,6 @@ public abstract class AbstractRenderer } } - /** - * Render the given Character. - * @param ch the character to render - * @deprecated Only TextArea should be used. This method will be removed eventually. - */ - protected void renderCharacter(Character ch) { - currentIPPosition += ch.getAllocIPD(); - } - /** * Common method to render the background and borders for any inline area. * The all borders and padding are drawn outside the specified area. @@ -754,6 +744,8 @@ public abstract class AbstractRenderer renderContainer((Container) content); } else if (content instanceof ForeignObject) { renderForeignObject((ForeignObject) content, contpos); + } else if (content instanceof InlineBlockParent) { + renderInlineBlockParent((InlineBlockParent) content); } currentIPPosition += viewport.getAllocIPD(); currentBPPosition = saveBP; @@ -792,7 +784,7 @@ public abstract class AbstractRenderer * @param pos The target position of the foreign object * (todo) Make renderForeignObject() protected */ - public void renderForeignObject(ForeignObject fo, Rectangle2D pos) { + protected void renderForeignObject(ForeignObject fo, Rectangle2D pos) { // Default: do nothing. // Some renderers (ex. Text) don't support foreign objects. } @@ -817,8 +809,9 @@ public abstract class AbstractRenderer handler.handleXML(ctx, doc, namespace); } catch (Exception e) { // could not handle document - ResourceEventProducer eventProducer = ResourceEventProducer.Provider.get( - ctx.getUserAgent().getEventBroadcaster()); + ResourceEventProducer eventProducer + = ResourceEventProducer.Provider.get( + ctx.getUserAgent().getEventBroadcaster()); eventProducer.foreignXMLProcessingError(this, doc, namespace, e); } } else { @@ -871,5 +864,4 @@ public abstract class AbstractRenderer matrix[5] = matrix[5] * 1000; return new AffineTransform(matrix); } - } diff --git a/src/java/org/apache/fop/render/pdf/PDFRenderer.java b/src/java/org/apache/fop/render/pdf/PDFRenderer.java index 0723d62f0..ff0e64806 100644 --- a/src/java/org/apache/fop/render/pdf/PDFRenderer.java +++ b/src/java/org/apache/fop/render/pdf/PDFRenderer.java @@ -1842,5 +1842,13 @@ public class PDFRenderer extends AbstractPathOrientedRenderer { public void setFilterMap(Map filterMap) { this.filterMap = filterMap; } + + /** + * Sets the encryption parameters used by the PDF renderer. + * @param encryptionParams the encryption parameters + */ + public void setEncryptionParams(PDFEncryptionParams encryptionParams) { + this.encryptionParams = encryptionParams; + } } diff --git a/src/java/org/apache/fop/render/pdf/PDFRendererConfigurator.java b/src/java/org/apache/fop/render/pdf/PDFRendererConfigurator.java index 2fce8859a..51e13dde1 100644 --- a/src/java/org/apache/fop/render/pdf/PDFRendererConfigurator.java +++ b/src/java/org/apache/fop/render/pdf/PDFRendererConfigurator.java @@ -28,6 +28,7 @@ import org.apache.avalon.framework.configuration.ConfigurationException; import org.apache.fop.apps.FOPException; import org.apache.fop.apps.FOUserAgent; import org.apache.fop.pdf.PDFAMode; +import org.apache.fop.pdf.PDFEncryptionParams; import org.apache.fop.pdf.PDFFilterList; import org.apache.fop.pdf.PDFXMode; import org.apache.fop.render.PrintRendererConfigurator; @@ -78,13 +79,54 @@ public class PDFRendererConfigurator extends PrintRendererConfigurator { if (s != null) { pdfRenderer.setXMode(PDFXMode.valueOf(s)); } + Configuration encryptionParamsConfig = cfg.getChild(PDFRenderer.ENCRYPTION_PARAMS, false); + if (encryptionParamsConfig != null) { + PDFEncryptionParams encryptionParams = new PDFEncryptionParams(); + Configuration ownerPasswordConfig = encryptionParamsConfig.getChild( + PDFRenderer.OWNER_PASSWORD, false); + if (ownerPasswordConfig != null) { + String ownerPassword = ownerPasswordConfig.getValue(null); + if (ownerPassword != null) { + encryptionParams.setOwnerPassword(ownerPassword); + } + } + Configuration userPasswordConfig = encryptionParamsConfig.getChild( + PDFRenderer.USER_PASSWORD, false); + if (userPasswordConfig != null) { + String userPassword = userPasswordConfig.getValue(null); + if (userPassword != null) { + encryptionParams.setUserPassword(userPassword); + } + } + Configuration noPrintConfig = encryptionParamsConfig.getChild( + PDFRenderer.NO_PRINT, false); + if (noPrintConfig != null) { + encryptionParams.setAllowPrint(false); + } + Configuration noCopyContentConfig = encryptionParamsConfig.getChild( + PDFRenderer.NO_COPY_CONTENT, false); + if (noCopyContentConfig != null) { + encryptionParams.setAllowCopyContent(false); + } + Configuration noEditContentConfig = encryptionParamsConfig.getChild( + PDFRenderer.NO_EDIT_CONTENT, false); + if (noEditContentConfig != null) { + encryptionParams.setAllowEditContent(false); + } + Configuration noAnnotationsConfig = encryptionParamsConfig.getChild( + PDFRenderer.NO_ANNOTATIONS, false); + if (noAnnotationsConfig != null) { + encryptionParams.setAllowEditAnnotations(false); + } + pdfRenderer.setEncryptionParams(encryptionParams); + } s = cfg.getChild(PDFRenderer.KEY_OUTPUT_PROFILE, true).getValue(null); if (s != null) { pdfRenderer.setOutputProfileURI(s); } - Configuration child = cfg.getChild(PDFRenderer.KEY_DISABLE_SRGB_COLORSPACE, false); - if (child != null) { - pdfRenderer.disableSRGBColorSpace = child.getValueAsBoolean(false); + Configuration disableColorSpaceConfig = cfg.getChild(PDFRenderer.KEY_DISABLE_SRGB_COLORSPACE, false); + if (disableColorSpaceConfig != null) { + pdfRenderer.disableSRGBColorSpace = disableColorSpaceConfig.getValueAsBoolean(false); } } } diff --git a/src/java/org/apache/fop/util/ConversionUtils.java b/src/java/org/apache/fop/util/ConversionUtils.java new file mode 100644 index 000000000..e2d93fbd3 --- /dev/null +++ b/src/java/org/apache/fop/util/ConversionUtils.java @@ -0,0 +1,110 @@ +/* + * 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.util; + +/** + * This class contains utility methods for conversions, like + * a java.lang.String to an array of int or double. + */ +public final class ConversionUtils { + + /** + * Converts the given base String into + * an array of int, splitting the base along the + * given separator pattern. + * Note: this method assumes the input is a string containing + * only decimal integers, signed or unsigned, that are parsable + * by java.lang.Integer.parseInt(String). If this + * is not the case, the resulting NumberFormatException + * will have to be handled by the caller. + * + * @param baseString the base string + * @param separatorPattern the pattern separating the integer values + * (if this is null, the baseString is parsed as one + * integer value) + * @return an array of int whose size is equal to the number + * values in the input string; null if this number + * is equal to zero. + */ + public static int[] toIntArray(String baseString, String separatorPattern) { + + if (baseString == null || "".equals(baseString)) { + return null; + } + + if (separatorPattern == null || "".equals(separatorPattern)) { + return new int[] { Integer.parseInt(baseString) }; + } + + String[] values = baseString.split(separatorPattern); + int numValues = values.length; + if (numValues == 0) { + return null; + } + + int[] returnArray = new int[numValues]; + for (int i = 0; i < numValues; ++i) { + returnArray[i] = Integer.parseInt(values[i]); + } + return returnArray; + + } + + /** + * Converts the given base String into + * an array of double, splitting the base along the + * given separator pattern. + * Note: this method assumes the input is a string containing + * only decimal doubles, signed or unsigned, that are parsable + * by java.lang.Double.parseDouble(String). If this + * is not the case, the resulting NumberFormatException + * will have to be handled by the caller. + * + * @param baseString the base string + * @param separatorPattern the pattern separating the integer values + * (if this is null, the baseString is parsed as one + * double value) + * @return an array of double whose size is equal to the number + * values in the input string; null if this number + * is equal to zero. + */ + public static double[] toDoubleArray(String baseString, String separatorPattern) { + + if (baseString == null || "".equals(baseString)) { + return null; + } + + if (separatorPattern == null || "".equals(separatorPattern)) { + return new double[] { Double.parseDouble(baseString) }; + } + + String[] values = baseString.split(separatorPattern); + int numValues = values.length; + if (numValues == 0) { + return null; + } + + double[] returnArray = new double[numValues]; + for (int i = 0; i < numValues; ++i) { + returnArray[i] = Double.parseDouble(values[i]); + } + return returnArray; + + } + +} diff --git a/status.xml b/status.xml index 42996789e..6f22165c5 100644 --- a/status.xml +++ b/status.xml @@ -53,6 +53,9 @@ + + Added PDF encryption parameter support in configuration. + Allowing non-zero borders and padding on page regions when relaxed validation is turned on. -- 2.39.5