From 774ae0ce7608497cf9477760d7f798de4d8f64eb Mon Sep 17 00:00:00 2001 From: Glen Mazza Date: Sat, 1 Nov 2003 14:23:49 +0000 Subject: [PATCH] Peter Herweg's RTF patches applied--note the RTFHandler update was missing, added similar changes as was done to the MIFHandler. git-svn-id: https://svn.apache.org/repos/asf/xmlgraphics/fop/trunk@196975 13f79535-47bb-0310-9956-ffa450edef68 --- .../org/apache/fop/fo/FOInputHandler.java | 12 + src/java/org/apache/fop/fo/FOTreeHandler.java | 15 + src/java/org/apache/fop/fo/flow/Inline.java | 9 + src/java/org/apache/fop/mif/MIFHandler.java | 15 + .../apache/fop/rtf/renderer/RTFHandler.java | 13 + .../rtf/renderer/TextAttributesConverter.java | 345 ++++++++++++++++++ .../rtflib/rtfdoc/IRtfTextrunContainer.java | 74 ++++ .../rtf/rtflib/rtfdoc/RtfAfterBeforeBase.java | 10 +- .../fop/rtf/rtflib/rtfdoc/RtfPageNumber.java | 6 + .../fop/rtf/rtflib/rtfdoc/RtfSection.java | 10 +- .../fop/rtf/rtflib/rtfdoc/RtfString.java | 100 +++++ .../fop/rtf/rtflib/rtfdoc/RtfTableCell.java | 10 +- .../apache/fop/rtf/rtflib/rtfdoc/RtfText.java | 4 +- .../fop/rtf/rtflib/rtfdoc/RtfTextrun.java | 286 +++++++++++++++ .../rtflib/rtfdoc/WhitespaceCollapser.java | 36 +- 15 files changed, 932 insertions(+), 13 deletions(-) create mode 100644 src/java/org/apache/fop/rtf/renderer/TextAttributesConverter.java create mode 100644 src/java/org/apache/fop/rtf/rtflib/rtfdoc/IRtfTextrunContainer.java create mode 100644 src/java/org/apache/fop/rtf/rtflib/rtfdoc/RtfString.java create mode 100644 src/java/org/apache/fop/rtf/rtflib/rtfdoc/RtfTextrun.java diff --git a/src/java/org/apache/fop/fo/FOInputHandler.java b/src/java/org/apache/fop/fo/FOInputHandler.java index 9b5254592..3e2000685 100644 --- a/src/java/org/apache/fop/fo/FOInputHandler.java +++ b/src/java/org/apache/fop/fo/FOInputHandler.java @@ -57,6 +57,7 @@ import org.apache.avalon.framework.logger.AbstractLogEnabled; import org.apache.fop.apps.FOPException; import org.apache.fop.fo.flow.Block; import org.apache.fop.fo.flow.ExternalGraphic; +import org.apache.fop.fo.flow.Inline; import org.apache.fop.fo.flow.InstreamForeignObject; import org.apache.fop.fo.flow.Leader; import org.apache.fop.fo.flow.ListBlock; @@ -170,6 +171,17 @@ public abstract class FOInputHandler extends AbstractLogEnabled { */ public abstract void endBlock(Block bl); + /** + * + * @param inl Inline that is starting. + */ + public abstract void startInline(Inline inl); + + /** + * + * @param inl Inline that is ending. + */ + public abstract void endInline(Inline inl); // Tables /** diff --git a/src/java/org/apache/fop/fo/FOTreeHandler.java b/src/java/org/apache/fop/fo/FOTreeHandler.java index 2362db1b9..d1dbab1d6 100644 --- a/src/java/org/apache/fop/fo/FOTreeHandler.java +++ b/src/java/org/apache/fop/fo/FOTreeHandler.java @@ -62,6 +62,7 @@ import org.apache.fop.apps.FOPException; import org.apache.fop.fo.flow.Block; import org.apache.fop.fo.flow.ExternalGraphic; import org.apache.fop.fo.flow.InstreamForeignObject; +import org.apache.fop.fo.flow.Inline; import org.apache.fop.fo.flow.Leader; import org.apache.fop.fo.flow.ListBlock; import org.apache.fop.fo.flow.ListItem; @@ -238,6 +239,20 @@ public class FOTreeHandler extends FOInputHandler { */ public void endBlock(Block bl) { } + + /** + * + * @param inl Inline that is starting. + */ + public void startInline(Inline inl){ + } + + /** + * + * @param inl Inline that is ending. + */ + public void endInline(Inline inl){ + } /** * @see org.apache.fop.fo.FOInputHandler#startTable(Table) diff --git a/src/java/org/apache/fop/fo/flow/Inline.java b/src/java/org/apache/fop/fo/flow/Inline.java index 05d3b3f35..3864b9bb2 100644 --- a/src/java/org/apache/fop/fo/flow/Inline.java +++ b/src/java/org/apache/fop/fo/flow/Inline.java @@ -146,6 +146,8 @@ public class Inline extends FObjMixed { if (textDecoration == TextDecoration.LINE_THROUGH) { this.lineThrough = true; } + + getFOTreeControl().getFOInputHandler().startInline(this); } /** @@ -166,4 +168,11 @@ public class Inline extends FObjMixed { fotv.serveInline(this); } + /** + * @see org.apache.fop.fo.FONode#end + */ + public void end() { + getFOTreeControl().getFOInputHandler().endInline(this); + } + } diff --git a/src/java/org/apache/fop/mif/MIFHandler.java b/src/java/org/apache/fop/mif/MIFHandler.java index b392c78d3..902ed9750 100644 --- a/src/java/org/apache/fop/mif/MIFHandler.java +++ b/src/java/org/apache/fop/mif/MIFHandler.java @@ -60,6 +60,7 @@ import org.apache.fop.fo.FOInputHandler; import org.apache.fop.fo.flow.Block; import org.apache.fop.fo.flow.ExternalGraphic; import org.apache.fop.fo.flow.InstreamForeignObject; +import org.apache.fop.fo.flow.Inline; import org.apache.fop.fo.flow.Leader; import org.apache.fop.fo.flow.ListBlock; import org.apache.fop.fo.flow.ListItem; @@ -222,6 +223,20 @@ public class MIFHandler extends FOInputHandler { para = null; } + /** + * + * @param inl Inline that is starting. + */ + public void startInline(Inline inl){ + } + + /** + * + * @param inl Inline that is ending. + */ + public void endInline(Inline inl){ + } + /** * @see org.apache.fop.fo.FOInputHandler#startTable(Table) */ diff --git a/src/java/org/apache/fop/rtf/renderer/RTFHandler.java b/src/java/org/apache/fop/rtf/renderer/RTFHandler.java index acd5ee2f6..c95ac439d 100644 --- a/src/java/org/apache/fop/rtf/renderer/RTFHandler.java +++ b/src/java/org/apache/fop/rtf/renderer/RTFHandler.java @@ -62,6 +62,7 @@ import org.apache.fop.datatypes.ColorType; import org.apache.fop.fo.FOInputHandler; import org.apache.fop.fo.flow.Block; import org.apache.fop.fo.flow.ExternalGraphic; +import org.apache.fop.fo.flow.Inline; import org.apache.fop.fo.flow.InstreamForeignObject; import org.apache.fop.fo.flow.Leader; import org.apache.fop.fo.flow.ListBlock; @@ -425,6 +426,18 @@ public class RTFHandler extends FOInputHandler { } /** + * @see org.apache.fop.fo.FOInputHandler#startInline(Inline) + */ + public void startInline(Inline inl){ + } + + /** + * @see org.apache.fop.fo.FOInputHandler#endInline(Inline) + */ + public void endInline(Inline inl){ + } + + /** * @see org.apache.fop.fo.FOInputHandler#startBody(TableBody) */ public void startBody(TableBody tb) { diff --git a/src/java/org/apache/fop/rtf/renderer/TextAttributesConverter.java b/src/java/org/apache/fop/rtf/renderer/TextAttributesConverter.java new file mode 100644 index 000000000..522cc8749 --- /dev/null +++ b/src/java/org/apache/fop/rtf/renderer/TextAttributesConverter.java @@ -0,0 +1,345 @@ +/* + * ============================================================================ + * The Apache Software License, Version 1.1 + * ============================================================================ + * + * Copyright (C) 1999-2003 The Apache Software Foundation. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without modifica- + * tion, are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materials provided with the distribution. + * + * 3. The end-user documentation included with the redistribution, if any, must + * include the following acknowledgment: "This product includes software + * developed by the Apache Software Foundation (http://www.apache.org/)." + * Alternately, this acknowledgment may appear in the software itself, if + * and wherever such third-party acknowledgments normally appear. + * + * 4. The names "FOP" and "Apache Software Foundation" must not be used to + * endorse or promote products derived from this software without prior + * written permission. For written permission, please contact + * apache@apache.org. + * + * 5. Products derived from this software may not be called "Apache", nor may + * "Apache" appear in their name, without prior written permission of the + * Apache Software Foundation. + * + * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED WARRANTIES, + * INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND + * FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE + * APACHE SOFTWARE FOUNDATION OR ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, + * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLU- + * DING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS + * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON + * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF + * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * ============================================================================ + * + * This software consists of voluntary contributions made by many individuals + * on behalf of the Apache Software Foundation and was originally created by + * James Tauber . For more information on the Apache + * Software Foundation, please see . + */ + +package org.apache.fop.rtf.renderer; + +//XML +import org.xml.sax.Attributes; + +//FOP +import org.apache.avalon.framework.logger.Logger; +import org.apache.avalon.framework.logger.ConsoleLogger; +import org.apache.fop.apps.FOPException; +import org.apache.fop.fo.EnumProperty; +import org.apache.fop.fo.expr.NCnameProperty; +import org.apache.fop.fo.properties.Constants; +import org.apache.fop.fo.LengthProperty; +import org.apache.fop.fo.ListProperty; +import org.apache.fop.fo.PropertyList; +import org.apache.fop.fo.Property; +import org.apache.fop.fo.SpaceProperty; +import org.apache.fop.fo.ColorTypeProperty; +import org.apache.fop.fo.NumberProperty; +import org.apache.fop.datatypes.ColorType; + +//RTF +import org.apache.fop.rtf.rtflib.rtfdoc.RtfAttributes; +import org.apache.fop.rtf.rtflib.rtfdoc.RtfColorTable; +import org.apache.fop.rtf.rtflib.rtfdoc.RtfFontManager; +import org.apache.fop.rtf.rtflib.rtfdoc.RtfText; + + +/** Converts FO properties to RtfAttributes + * @author Bertrand Delacretaz bdelacretaz@codeconsult.ch + * @author Andreas Putz a.putz@skynamics.com + * @author Boris Poudérous boris.pouderous@eads-telecom.com + * @author Peter Herweg, pherweg@web.de + * @author Normand Massé + * @author Chris Scott + * @author rmarra + */ + +class TextAttributesConverter { + private static Logger log = new ConsoleLogger(); + + /** + * Converts all known text FO properties to RtfAttributes + * @param props list of FO properites, which are to be converted + * @param props list of default FO properites (usally null) + */ + public static RtfAttributes convertAttributes(PropertyList props, PropertyList defProps) + throws FOPException { + RtfAttributes attrib = null; + + if (defProps != null) { + attrib = convertAttributes(defProps, null); + } else { + attrib = new RtfAttributes(); + } + + attrBlockFontFamily(props, attrib); + attrBlockFontWeight(props, attrib); + attrBlockFontSize(props, attrib); + attrBlockFontColor(props, attrib); + attrBlockFontItalic(props, attrib); + attrBlockFontUnderline(props, attrib); + attrBlockBackgroundColor(props, attrib); + attrBlockSpaceBeforeAfter(props, attrib); + attrBlockMargins(props, attrib); + attrBlockTextAlign(props, attrib); + + return attrib; + } + + /** + * Converts all character related FO properties to RtfAttributes. + * @param props list of FO properites, which are to be converted + * @param props list of default FO properites (usally null) + */ + public static RtfAttributes convertCharacterAttributes(PropertyList props, PropertyList defProps) + throws FOPException { + + RtfAttributes attrib = null; + + if (defProps != null) { + attrib = convertCharacterAttributes(defProps, null); + } else { + attrib = new RtfAttributes(); + } + + attrBlockFontFamily(props, attrib); + attrBlockFontWeight(props, attrib); + attrBlockFontSize(props, attrib); + attrBlockFontColor(props, attrib); + attrBlockFontItalic(props, attrib); + attrBlockFontUnderline(props, attrib); + attrBlockBackgroundColor(props, attrib); + + return attrib; + } + + + private static void attrBlockFontFamily(PropertyList properties, RtfAttributes rtfAttr) { + String fopValue = properties.get("font-family").getString(); + + if (fopValue != null) { + rtfAttr.set(RtfText.ATTR_FONT_FAMILY, RtfFontManager.getInstance().getFontNumber(fopValue)); + } + } + + private static void attrBlockFontSize(PropertyList properties, RtfAttributes rtfAttr) { + int fopValue = properties.get("font-size").getLength().getValue() / 500; + rtfAttr.set("fs", fopValue); + } + + private static void attrBlockFontColor(PropertyList properties, RtfAttributes rtfAttr) { + // Cell background color + ColorTypeProperty colorTypeProp=(ColorTypeProperty)properties.get("color"); + if(colorTypeProp != null) { + ColorType colorType = colorTypeProp.getColorType(); + if (colorType != null) { + if (colorType.getAlpha() != 0 + || colorType.getRed() != 0 + || colorType.getGreen() != 0 + || colorType.getBlue() != 0) { + rtfAttr.set( + RtfText.ATTR_FONT_COLOR, + convertFOPColorToRTF(colorType)); + } + } else { + log.warn("Named color '" + colorTypeProp.toString() + "' not found. "); + } + } + } + + + + private static void attrBlockFontWeight(PropertyList properties, RtfAttributes rtfAttr) { + String fopValue = properties.get("font-weight").getString(); + if (fopValue == "bold" || fopValue == "700") { + rtfAttr.set("b", 1); + } else { + rtfAttr.set("b", 0); + } + } + + private static void attrBlockFontItalic(PropertyList properties, RtfAttributes rtfAttr) { + String fopValue = properties.get("font-style").getString(); + if(fopValue.equals("italic")) { + rtfAttr.set(RtfText.ATTR_ITALIC, 1); + } else { + rtfAttr.set(RtfText.ATTR_ITALIC, 0); + } + } + + private static void attrBlockFontUnderline(PropertyList properties, RtfAttributes rtfAttr) { + EnumProperty enumProp=(EnumProperty)properties.get("text-decoration"); + if(enumProp.getEnum()==Constants.UNDERLINE) { + rtfAttr.set(RtfText.ATTR_UNDERLINE, 1); + } else { + rtfAttr.set(RtfText.ATTR_UNDERLINE, 0); + } + } + + private static void attrBlockSpaceBeforeAfter(PropertyList properties, RtfAttributes rtfAttr) { + SpaceProperty spaceProp=null; + + //space-before + spaceProp=(SpaceProperty)properties.get("space-before"); + if(spaceProp!=null) { + Float f = new Float(spaceProp.getLengthRange().getOptimum().getLength().getValue() / 1000f); + String sValue = f.toString() + "pt"; + + try { + rtfAttr.set( + RtfText.SPACE_BEFORE, + (int)FoUnitsConverter.getInstance().convertToTwips(sValue)); + } catch(FOPException fe) { + log.warn("attrBlockSpaceBeforeAfter: " + fe.getMessage()); + } + } + + //space-after + spaceProp=(SpaceProperty)properties.get("space-after"); + if(spaceProp!=null) { + Float f = new Float(spaceProp.getLengthRange().getOptimum().getLength().getValue() / 1000f); + String sValue = f.toString() + "pt"; + + try { + rtfAttr.set( + RtfText.SPACE_AFTER, + (int)FoUnitsConverter.getInstance().convertToTwips(sValue)); + } catch(FOPException fe) { + log.warn("attrBlockSpaceBeforeAfter: " + fe.getMessage()); + } + } + } + + private static void attrBlockMargins(PropertyList properties, RtfAttributes rtfAttr) { + try { + LengthProperty lengthProp=null; + + // margin-left + lengthProp=(LengthProperty)properties.get("margin-left"); + if (lengthProp != null) { + Float f = new Float(lengthProp.getLength().getValue() / 1000f); + String sValue = f.toString() + "pt"; + + rtfAttr.set( + RtfText.LEFT_INDENT_BODY, + (int)FoUnitsConverter.getInstance().convertToTwips(sValue)); + } else { + rtfAttr.set(RtfText.LEFT_INDENT_BODY, 0); + } + + // margin-right + lengthProp=(LengthProperty)properties.get("margin-right"); + if (lengthProp != null) { + Float f = new Float(lengthProp.getLength().getValue() / 1000f); + String sValue = f.toString() + "pt"; + + rtfAttr.set( + RtfText.LEFT_INDENT_BODY, + (int)FoUnitsConverter.getInstance().convertToTwips(sValue)); + } else { + rtfAttr.set(RtfText.RIGHT_INDENT_BODY, 0); + } + } catch(FOPException fe) { + log.warn("attrBlockSpaceBeforeAfter: " + fe.getMessage()); + } + } + + + + private static void attrBlockTextAlign(PropertyList properties, RtfAttributes rtfAttr) { + int fopValue = properties.get("text-align").getEnum(); + String rtfValue = null; + switch (fopValue) { + case Constants.CENTER: { + rtfValue = RtfText.ALIGN_CENTER; + break; + } + case Constants.END: { + rtfValue = RtfText.ALIGN_RIGHT; + break; + } + case Constants.JUSTIFY: { + rtfValue = RtfText.ALIGN_JUSTIFIED; + break; + } + default: { + rtfValue = RtfText.ALIGN_LEFT; + break; + } + } + + rtfAttr.set(rtfValue); + } + + /** + * Reads background-color from bl and writes it to rtfAttr. + * + * @param bl the Block object the properties are read from + * @param rtfAttr the RtfAttributes object the attributes are written to + */ + private static void attrBlockBackgroundColor(PropertyList properties, RtfAttributes rtfAttr) { + ColorType fopValue = properties.get("background-color").getColorType(); + int rtfColor = 0; + /* FOP uses a default background color of "transparent", which is + actually a transparent black, which is generally not suitable as a + default here. Changing FOP's default to "white" causes problems in + PDF output, so we will look for the default here & change it to + "auto". */ + if ((fopValue.getRed() == 0) + && (fopValue.getGreen() == 0) + && (fopValue.getBlue() == 0) + && (fopValue.getAlpha() == 0)) { + rtfColor = 0; //=auto + } else { + rtfColor = convertFOPColorToRTF(fopValue); + } + + rtfAttr.set(RtfText.ATTR_BACKGROUND_COLOR, rtfColor); + } + + /** + * Converts a FOP ColorType to the integer pointing into the RTF color table + * @param fopColor the ColorType object to be converted + * @return integer pointing into the RTF color table + */ + public static int convertFOPColorToRTF(ColorType fopColor) { + int redComponent = ColorType.convertChannelToInteger (fopColor.getRed()); + int greenComponent = ColorType.convertChannelToInteger (fopColor.getGreen()); + int blueComponent = ColorType.convertChannelToInteger (fopColor.getBlue()); + return RtfColorTable.getInstance().getColorNumber(redComponent, + greenComponent, blueComponent).intValue(); + } + +} diff --git a/src/java/org/apache/fop/rtf/rtflib/rtfdoc/IRtfTextrunContainer.java b/src/java/org/apache/fop/rtf/rtflib/rtfdoc/IRtfTextrunContainer.java new file mode 100644 index 000000000..f8d115980 --- /dev/null +++ b/src/java/org/apache/fop/rtf/rtflib/rtfdoc/IRtfTextrunContainer.java @@ -0,0 +1,74 @@ +/* + * ============================================================================ + * The Apache Software License, Version 1.1 + * ============================================================================ + * + * Copyright (C) 1999-2003 The Apache Software Foundation. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without modifica- + * tion, are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materials provided with the distribution. + * + * 3. The end-user documentation included with the redistribution, if any, must + * include the following acknowledgment: "This product includes software + * developed by the Apache Software Foundation (http://www.apache.org/)." + * Alternately, this acknowledgment may appear in the software itself, if + * and wherever such third-party acknowledgments normally appear. + * + * 4. The names "FOP" and "Apache Software Foundation" must not be used to + * endorse or promote products derived from this software without prior + * written permission. For written permission, please contact + * apache@apache.org. + * + * 5. Products derived from this software may not be called "Apache", nor may + * "Apache" appear in their name, without prior written permission of the + * Apache Software Foundation. + * + * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED WARRANTIES, + * INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND + * FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE + * APACHE SOFTWARE FOUNDATION OR ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, + * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLU- + * DING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS + * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON + * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF + * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * ============================================================================ + * + * This software consists of voluntary contributions made by many individuals + * on behalf of the Apache Software Foundation and was originally created by + * James Tauber . For more information on the Apache + * Software Foundation, please see . + */ + + +/* + * This file is part of the RTF library of the FOP project. + */ + + +package org.apache.fop.rtf.rtflib.rtfdoc; + +import java.io.IOException; +import java.io.Writer; +import java.util.LinkedList; +import java.util.List; +import java.util.Iterator; +import java.io.IOException; +import org.apache.fop.rtf.rtflib.exceptions.RtfStructureException; +import org.apache.fop.rtf.rtflib.rtfdoc.RtfTextrun; + +/** Interface which enables an implementing class to contain linear text runs. + * @author Peter Herweg, pherweg@web.de + */ + +public interface IRtfTextrunContainer { + public RtfTextrun getTextrun() throws IOException; +} diff --git a/src/java/org/apache/fop/rtf/rtflib/rtfdoc/RtfAfterBeforeBase.java b/src/java/org/apache/fop/rtf/rtflib/rtfdoc/RtfAfterBeforeBase.java index 93cc15701..14d20e9ae 100644 --- a/src/java/org/apache/fop/rtf/rtflib/rtfdoc/RtfAfterBeforeBase.java +++ b/src/java/org/apache/fop/rtf/rtflib/rtfdoc/RtfAfterBeforeBase.java @@ -70,7 +70,8 @@ import org.apache.fop.rtf.rtflib.interfaces.ITableColumnsInfo; abstract class RtfAfterBeforeBase extends RtfContainer -implements IRtfParagraphContainer, IRtfExternalGraphicContainer, IRtfTableContainer { +implements IRtfParagraphContainer, IRtfExternalGraphicContainer, IRtfTableContainer, + IRtfTextrunContainer { protected RtfAttributes attrib; private RtfParagraph para; private RtfExternalGraphic externalGraphic; @@ -155,4 +156,9 @@ implements IRtfParagraphContainer, IRtfExternalGraphicContainer, IRtfTableContai table = new RtfTable(this, writer, tc); return table; } -} \ No newline at end of file + + public RtfTextrun getTextrun() + throws IOException { + return RtfTextrun.getTextrun(this, writer, null); + } +} diff --git a/src/java/org/apache/fop/rtf/rtflib/rtfdoc/RtfPageNumber.java b/src/java/org/apache/fop/rtf/rtflib/rtfdoc/RtfPageNumber.java index 1d3d4ce37..0355cddaf 100644 --- a/src/java/org/apache/fop/rtf/rtflib/rtfdoc/RtfPageNumber.java +++ b/src/java/org/apache/fop/rtf/rtflib/rtfdoc/RtfPageNumber.java @@ -83,6 +83,12 @@ public class RtfPageNumber extends RtfContainer { super((RtfContainer)parent, w); } + /** Create an RTF page number as a child of given container with given attributes */ + RtfPageNumber(RtfContainer parent, Writer w, RtfAttributes attrs) throws IOException { + // Adds the attributes of the parent paragraph + super(parent, w, attrs); + } + /** Create an RTF page number as a child of given paragraph, * copying the paragraph attributes */ diff --git a/src/java/org/apache/fop/rtf/rtflib/rtfdoc/RtfSection.java b/src/java/org/apache/fop/rtf/rtflib/rtfdoc/RtfSection.java index ae915ba75..d6a254136 100755 --- a/src/java/org/apache/fop/rtf/rtflib/rtfdoc/RtfSection.java +++ b/src/java/org/apache/fop/rtf/rtflib/rtfdoc/RtfSection.java @@ -76,7 +76,8 @@ implements IRtfBeforeContainer, IRtfParagraphKeepTogetherContainer, IRtfAfterContainer, - IRtfJforCmdContainer { + IRtfJforCmdContainer, + IRtfTextrunContainer { private RtfParagraph paragraph; private RtfTable table; private RtfList list; @@ -262,4 +263,9 @@ implements closeCurrentExternalGraphic(); closeCurrentBefore(); } -} \ No newline at end of file + + public RtfTextrun getTextrun() + throws IOException { + return RtfTextrun.getTextrun(this, writer, null); + } +} diff --git a/src/java/org/apache/fop/rtf/rtflib/rtfdoc/RtfString.java b/src/java/org/apache/fop/rtf/rtflib/rtfdoc/RtfString.java new file mode 100644 index 000000000..7bb3837bf --- /dev/null +++ b/src/java/org/apache/fop/rtf/rtflib/rtfdoc/RtfString.java @@ -0,0 +1,100 @@ +/* + * ============================================================================ + * The Apache Software License, Version 1.1 + * ============================================================================ + * + * Copyright (C) 1999-2003 The Apache Software Foundation. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without modifica- + * tion, are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materials provided with the distribution. + * + * 3. The end-user documentation included with the redistribution, if any, must + * include the following acknowledgment: "This product includes software + * developed by the Apache Software Foundation (http://www.apache.org/)." + * Alternately, this acknowledgment may appear in the software itself, if + * and wherever such third-party acknowledgments normally appear. + * + * 4. The names "FOP" and "Apache Software Foundation" must not be used to + * endorse or promote products derived from this software without prior + * written permission. For written permission, please contact + * apache@apache.org. + * + * 5. Products derived from this software may not be called "Apache", nor may + * "Apache" appear in their name, without prior written permission of the + * Apache Software Foundation. + * + * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED WARRANTIES, + * INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND + * FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE + * APACHE SOFTWARE FOUNDATION OR ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, + * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLU- + * DING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS + * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON + * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF + * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * ============================================================================ + * + * This software consists of voluntary contributions made by many individuals + * on behalf of the Apache Software Foundation and was originally created by + * James Tauber . For more information on the Apache + * Software Foundation, please see . + */ + +/* + * This file is part of the RTF library of the FOP project, which was originally + * created by Bertrand Delacretaz and by other + * contributors to the jfor project (www.jfor.org), who agreed to donate jfor to + * the FOP project. + */ + +package org.apache.fop.rtf.rtflib.rtfdoc; + +import java.io.IOException; +import java.io.Writer; + +/** Plain text in a RTF file, without any formatings. + * @author Peter Herweg, pherweg@web.de + */ + +public class RtfString extends RtfElement +{ + String text=""; + + RtfString(RtfContainer parent, Writer w, String s) + throws IOException { + super(parent, w); + + text=s; + } + + /** + * @return true if this element would generate no "useful" RTF content + */ + public boolean isEmpty() { + return text.trim().equals(""); + } + + /** + * write RTF code of all our children + * @throws IOException for I/O problems + */ + protected void writeRtfContent() throws IOException { + RtfStringConverter.getInstance().writeRtfString(writer, text); + } + + public String getText() { + return text; + } + + public void setText(String s) { + text=s; + } +} \ No newline at end of file diff --git a/src/java/org/apache/fop/rtf/rtflib/rtfdoc/RtfTableCell.java b/src/java/org/apache/fop/rtf/rtflib/rtfdoc/RtfTableCell.java index 9695782e0..87098e4b5 100755 --- a/src/java/org/apache/fop/rtf/rtflib/rtfdoc/RtfTableCell.java +++ b/src/java/org/apache/fop/rtf/rtflib/rtfdoc/RtfTableCell.java @@ -70,7 +70,7 @@ import org.apache.fop.rtf.rtflib.interfaces.ITableColumnsInfo; public class RtfTableCell extends RtfContainer implements IRtfParagraphContainer, IRtfListContainer, IRtfTableContainer, - IRtfExternalGraphicContainer { + IRtfExternalGraphicContainer, IRtfTextrunContainer { private RtfParagraph paragraph; private RtfList list; private RtfTable table; @@ -475,4 +475,12 @@ implements IRtfParagraphContainer, IRtfListContainer, IRtfTableContainer, } return result; } + + public RtfTextrun getTextrun() + throws IOException { + RtfAttributes attrs = new RtfAttributes(); + attrs.set("intbl"); + + return RtfTextrun.getTextrun(this, writer, attrs); + } } diff --git a/src/java/org/apache/fop/rtf/rtflib/rtfdoc/RtfText.java b/src/java/org/apache/fop/rtf/rtflib/rtfdoc/RtfText.java index 0525cdd0d..c1179134a 100755 --- a/src/java/org/apache/fop/rtf/rtflib/rtfdoc/RtfText.java +++ b/src/java/org/apache/fop/rtf/rtflib/rtfdoc/RtfText.java @@ -143,6 +143,8 @@ public class RtfText extends RtfElement { public static final String LEFT_INDENT_BODY = "li"; /** constant for left indent first */ public static final String LEFT_INDENT_FIRST = "fi-"; + /** constant for right indent body */ + public static final String RIGHT_INDENT_BODY = "ri"; /** constant for center tab */ public static final String TAB_CENTER = "tqc\\tx"; @@ -285,7 +287,7 @@ public class RtfText extends RtfElement { /** * True if text contains a single non-breaking space (#160). - * TODO make this more general and/or merge with isEmpty? <-- what happen + * TODO make this more general and/or merge with isEmpty? -- what happen * with empty paragraphs, if they will be removed, than NO, else ok * * @return true If m_text is character 160\n diff --git a/src/java/org/apache/fop/rtf/rtflib/rtfdoc/RtfTextrun.java b/src/java/org/apache/fop/rtf/rtflib/rtfdoc/RtfTextrun.java new file mode 100644 index 000000000..bc6843cbf --- /dev/null +++ b/src/java/org/apache/fop/rtf/rtflib/rtfdoc/RtfTextrun.java @@ -0,0 +1,286 @@ +/* + * ============================================================================ + * The Apache Software License, Version 1.1 + * ============================================================================ + * + * Copyright (C) 1999-2003 The Apache Software Foundation. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without modifica- + * tion, are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materials provided with the distribution. + * + * 3. The end-user documentation included with the redistribution, if any, must + * include the following acknowledgment: "This product includes software + * developed by the Apache Software Foundation (http://www.apache.org/)." + * Alternately, this acknowledgment may appear in the software itself, if + * and wherever such third-party acknowledgments normally appear. + * + * 4. The names "FOP" and "Apache Software Foundation" must not be used to + * endorse or promote products derived from this software without prior + * written permission. For written permission, please contact + * apache@apache.org. + * + * 5. Products derived from this software may not be called "Apache", nor may + * "Apache" appear in their name, without prior written permission of the + * Apache Software Foundation. + * + * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED WARRANTIES, + * INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND + * FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE + * APACHE SOFTWARE FOUNDATION OR ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, + * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLU- + * DING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS + * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON + * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF + * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * ============================================================================ + * + * This software consists of voluntary contributions made by many individuals + * on behalf of the Apache Software Foundation and was originally created by + * James Tauber . For more information on the Apache + * Software Foundation, please see . + */ + + +/* + * This file is part of the RTF library of the FOP project. + */ + + +package org.apache.fop.rtf.rtflib.rtfdoc; + +import java.io.IOException; +import java.io.Writer; +import java.util.LinkedList; +import java.util.List; +import java.util.Iterator; +import java.io.IOException; +import org.apache.fop.rtf.rtflib.exceptions.RtfStructureException; + +/** Class which contains a linear text run. It has methods to add attributes, text, paragraph breaks.... + * @author Peter Herweg, pherweg@web.de + */ + +public class RtfTextrun extends RtfContainer { + + /** Class which represents the opening of a RTF group mark.*/ + private class RtfOpenGroupMark extends RtfElement + { + RtfOpenGroupMark(RtfContainer parent, Writer w, RtfAttributes attr) + throws IOException { + super(parent, w, attr); + } + + /** + * @return true if this element would generate no "useful" RTF content + */ + public boolean isEmpty() { + return false; + } + + /** + * write RTF code of all our children + * @throws IOException for I/O problems + */ + protected void writeRtfContent() throws IOException { + writeGroupMark(true); + writeAttributes(getRtfAttributes(), null); + } + } + + /** Class which represents the closing of a RTF group mark.*/ + private class RtfCloseGroupMark extends RtfElement + { + RtfCloseGroupMark(RtfContainer parent, Writer w) + throws IOException { + super(parent, w); + } + + /** + * @return true if this element would generate no "useful" RTF content + */ + public boolean isEmpty() { + return false; + } + + /** + * write RTF code of all our children + * @throws IOException for I/O problems + */ + protected void writeRtfContent() throws IOException { + writeGroupMark(false); + } + } + + /** Class which represents a paragraph break.*/ + private class RtfParagraphBreak extends RtfElement + { + RtfParagraphBreak(RtfContainer parent, Writer w) + throws IOException { + super(parent, w); + } + + /** + * @return true if this element would generate no "useful" RTF content + */ + public boolean isEmpty() { + return false; + } + + /** + * write RTF code of all our children + * @throws IOException for I/O problems + */ + protected void writeRtfContent() throws IOException { + writeControlWord("par"); + } + } + + /** Create an RTF container as a child of given container */ + RtfTextrun(RtfContainer parent, Writer w, RtfAttributes attrs) throws IOException { + super(parent, w, attrs); + } + + public void pushAttributes(RtfAttributes attrs) throws IOException { + RtfOpenGroupMark r=new RtfOpenGroupMark(this, writer, attrs); + } + + public void popAttributes() throws IOException { + RtfCloseGroupMark r=new RtfCloseGroupMark(this, writer); + } + + public void addString(String s) throws IOException { + RtfString r=new RtfString(this, writer, s); + } + + public void addParagraphBreak() throws IOException { + RtfParagraphBreak r=new RtfParagraphBreak(this, writer); + } + + public void addPageNumber(RtfAttributes attr) throws IOException { + RtfPageNumber r=new RtfPageNumber(this, writer, attr); + } + + /** + * Adds a new RtfTextrun to the given container if necessary, and returns it. + * @param container RtfContainer, which is the parent of the returned RtfTextrun + * @param writer Writer of the given RtfContainer + * @param attrs RtfAttributes which are to write at the beginning of the RtfTextrun + * @throws IOException for I/O problems + */ + public static RtfTextrun getTextrun(RtfContainer container, Writer writer, RtfAttributes attrs) + throws IOException { + Object obj; + List list=container.getChildren(); + + if(list.size()==0) { + //add a new RtfTextrun + RtfTextrun textrun=new RtfTextrun(container, writer, attrs); + list.add(textrun); + + return textrun; + } else if ((obj=list.get(list.size()-1)) instanceof RtfTextrun ) { + //if the last child is a RtfTextrun, return it + return (RtfTextrun)obj; + } + + //add a new RtfTextrun as the last child + RtfTextrun textrun=new RtfTextrun(container, writer, attrs); + list.add(textrun); + + return textrun; + } + + /** + * write RTF code of all our children + * @throws IOException for I/O problems + */ + protected void writeRtfContent() throws IOException { + /** + *TODO: The textrun's children are iterated threetimes: + * 1. In WhitespaceCollapser + * 2. To determine the last RtfParagraphBreak + * 3. To write the children + * Maybe this can be done more efficient. + */ + + if (attrib != null && attrib.isSet("WhiteSpaceFalse")) { + attrib.unset("WhiteSpaceFalse"); + } else { + new WhitespaceCollapser(this); + } + + //determine, if this RtfTextrun is the last child of its parent + boolean bLast=false; + for (Iterator it = parent.getChildren().iterator(); it.hasNext();) { + if(it.next() == this) { + bLast=!it.hasNext(); + break; + } + } + + //get last RtfParagraphBreak, which is not followed by any visible child + RtfParagraphBreak lastParagraphBreak=null; + if(bLast) { + for (Iterator it = getChildren().iterator(); it.hasNext();) { + final RtfElement e = (RtfElement)it.next(); + if(e instanceof RtfParagraphBreak) { + lastParagraphBreak=(RtfParagraphBreak)e; + } else { + if(!(e instanceof RtfOpenGroupMark) + && !(e instanceof RtfCloseGroupMark) + && e.isEmpty()) { + lastParagraphBreak=null; + } + } + } + } + + //may contain for example \intbl + writeAttributes(attrib, null); + + //write all children + boolean bPrevPar = false; + boolean bFirst = true; + for (Iterator it = getChildren().iterator(); it.hasNext();) { + final RtfElement e = (RtfElement)it.next(); + final boolean bRtfParagraphBreak = (e instanceof RtfParagraphBreak); + + /** + * -Write RtfParagraphBreak only, if the previous visible child + * was't also a RtfParagraphBreak. + * -Write RtfParagraphBreak only, if it is not the first visible + * child. + * -If the RtfTextrun is the last child of its parent, write a + * RtfParagraphBreak only, if it is not the last child. + */ + boolean bHide=false; + bHide=bRtfParagraphBreak; + bHide=bHide && + (bPrevPar || bFirst || (bLast && lastParagraphBreak!=null && e==lastParagraphBreak) ); + + if( !bHide) { + e.writeRtf(); + } + + if(e instanceof RtfParagraphBreak) { + bPrevPar=true; + } else if(e instanceof RtfCloseGroupMark) { + //do nothing + } else if(e instanceof RtfOpenGroupMark) { + //do nothing + } else { + bPrevPar=bPrevPar && e.isEmpty(); + bFirst=bFirst && e.isEmpty(); + } + } + } +} + diff --git a/src/java/org/apache/fop/rtf/rtflib/rtfdoc/WhitespaceCollapser.java b/src/java/org/apache/fop/rtf/rtflib/rtfdoc/WhitespaceCollapser.java index e795106fa..438612594 100755 --- a/src/java/org/apache/fop/rtf/rtflib/rtfdoc/WhitespaceCollapser.java +++ b/src/java/org/apache/fop/rtf/rtflib/rtfdoc/WhitespaceCollapser.java @@ -73,11 +73,13 @@ class WhitespaceCollapser { WhitespaceCollapser(RtfContainer c) { // process all texts for (Iterator it = c.getChildren().iterator(); it.hasNext();) { - RtfText current = null; final Object kid = it.next(); if (kid instanceof RtfText) { - current = (RtfText)kid; + RtfText current = (RtfText)kid; processText(current); + } else if (kid instanceof RtfString) { + RtfString current = (RtfString)kid; + processString(current); } else { // if there is something between two texts, it counts for a space lastEndSpace = true; @@ -87,11 +89,29 @@ class WhitespaceCollapser { /** process one RtfText from our container */ private void processText(RtfText txt) { - final String orig = txt.getText(); + final String newString=processString(txt.getText()); + if(newString!=null) { + txt.setText(newString); + } + } + + /** process one RtfString from our container */ + private void processString(RtfString txt) { + final String newString=processString(txt.getText()); + if(newString!=null) { + txt.setText(newString); + } + } + + /** process one String */ + private String processString(String txt) { + final String orig = txt; // tokenize the text based on whitespace and regenerate it so as // to collapse multiple spaces into one - if (orig != null && orig.length() > 0) { + if(orig==null) { + return null; + } else if (orig.length() > 0) { final boolean allSpaces = orig.trim().length() == 0; final boolean endSpace = allSpaces || Character.isWhitespace(orig.charAt(orig.length() - 1)); @@ -107,7 +127,7 @@ class WhitespaceCollapser { // TODO to be compatible with different Locales, should use Character.isWhitespace // instead of this limited list boolean first = true; - final StringTokenizer stk = new StringTokenizer(txt.getText(), " \t\n\r"); + final StringTokenizer stk = new StringTokenizer(txt, " \t\n\r"); while (stk.hasMoreTokens()) { if (first && beginSpace && !lastEndSpace) { sb.append(SPACE); @@ -121,8 +141,10 @@ class WhitespaceCollapser { } } - txt.setText(sb.toString()); lastEndSpace = endSpace; + return sb.toString(); + } else { + return ""; } } -} \ No newline at end of file +} -- 2.39.5