From: William Victor Mote Date: Thu, 18 Sep 2003 15:57:25 +0000 (+0000) Subject: changes for RTF tables, submitted by Peter Herweg, see http://nagoya.apache.org/bugzi... X-Git-Tag: Root_Temp_KnuthStylePageBreaking~1085 X-Git-Url: https://source.dussan.org/?a=commitdiff_plain;h=1519516c352043282afe61f8b425cff5788f40d1;p=xmlgraphics-fop.git changes for RTF tables, submitted by Peter Herweg, see http://nagoya.apache.org/bugzilla/show_bug.cgi?id=23166 git-svn-id: https://svn.apache.org/repos/asf/xmlgraphics/fop/trunk@196921 13f79535-47bb-0310-9956-ffa450edef68 --- diff --git a/src/java/org/apache/fop/fo/flow/TableBody.java b/src/java/org/apache/fop/fo/flow/TableBody.java index 71cd68b85..474acc814 100644 --- a/src/java/org/apache/fop/fo/flow/TableBody.java +++ b/src/java/org/apache/fop/fo/flow/TableBody.java @@ -50,6 +50,9 @@ */ package org.apache.fop.fo.flow; +// XML +import org.xml.sax.Attributes; + // FOP import org.apache.fop.apps.FOPException; import org.apache.fop.datatypes.ColorType; @@ -123,5 +126,20 @@ public class TableBody extends FObj { fotv.serveTableBody(this); } + /** + * @see org.apache.fop.fo.FObj#handleAttrs + */ + public void handleAttrs(Attributes attlist) throws FOPException { + super.handleAttrs(attlist); + + setupID(); + + getFOTreeControl().getFOInputHandler().startBody(this); + } + + protected void end() { + getFOTreeControl().getFOInputHandler().endBody(this); + } + } diff --git a/src/java/org/apache/fop/rtf/renderer/BuilderContext.java b/src/java/org/apache/fop/rtf/renderer/BuilderContext.java new file mode 100644 index 000000000..00e41c524 --- /dev/null +++ b/src/java/org/apache/fop/rtf/renderer/BuilderContext.java @@ -0,0 +1,199 @@ +/* + * ============================================================================ + * 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; + +import java.util.Stack; +import org.apache.fop.rtf.rtflib.rtfdoc.*; + + +/** A BuilderContext holds context information when building an RTF document + * + * @author Bertrand Delacretaz + * @author putzi + * @author Peter Herweg + * + * This class was originally developed by Bertrand Delacretaz bdelacretaz@codeconsult.ch + * for the JFOR project and is now integrated into FOP. + */ + + +class BuilderContext +{ + /** stack of RtfContainers */ + private final Stack m_containers = new Stack(); + + /** stack of TableContexts */ + private final Stack m_tableContexts = new Stack(); + + /** stack of IBuilders */ + private final Stack m_builders = new Stack(); + + /** Rtf options */ + IRtfOptions m_options; + + BuilderContext(IRtfOptions rtfOptions) + { + m_options = rtfOptions; + } + + /** find first object of given class from top of stack s + * @return null if not found + */ + private Object getObjectFromStack(Stack s,Class desiredClass) + { + Object result = null; + final Stack copy = (Stack)s.clone(); + while(!copy.isEmpty()) { + final Object o = copy.pop(); + if(desiredClass.isAssignableFrom(o.getClass())) { + result = o; + break; + } + } + return result; + } + + /* find the "nearest" IBuilder of given class / + Object getBuilder(Class builderClass,boolean required) + throws Exception + { + final IBuilder result = (IBuilder)getObjectFromStack(m_builders,builderClass); + if(result == null && required) { + throw new Exception( + "IBuilder of class '" + builderClass.getName() + "' not found on builders stack" + ); + } + return result; + }*/ + + /** find the "nearest" container that implements the given interface on our stack + * @param required if true, ConverterException is thrown if no container found + * @param forWhichBuilder used in error message if container not found + */ + RtfContainer getContainer(Class containerClass,boolean required,Object /*IBuilder*/ forWhichBuilder) throws Exception + { + // TODO what to do if the desired container is not at the top of the stack? + // close top-of-stack container? + final RtfContainer result = (RtfContainer)getObjectFromStack(m_containers,containerClass); + + if(result == null && required) { + throw new Exception( + "No RtfContainer of class '" + containerClass.getName() + + "' available for '" + forWhichBuilder.getClass().getName() + "' builder" + ); + } + + return result; + } + + /** push an RtfContainer on our stack */ + void pushContainer(RtfContainer c) + { + m_containers.push(c); + } + + /** in some cases an RtfContainer must be replaced by another one on the stack. + * this happens when handling nested fo:blocks for example: after handling a nested block + * the enclosing block must switch to a new paragraph container to handle what follows the nested block. + * TODO: what happens to elements that are "more on top" than oldC on the stack? shouldn't they be closed + * or something? + */ + void replaceContainer(RtfContainer oldC,RtfContainer newC) + throws Exception + { + // treating the Stack as a Vector allows such manipulations (yes, I hear you screaming ;-) + final int index = m_containers.indexOf(oldC); + if(index < 0) throw new Exception("container to replace not found:" + oldC); + m_containers.setElementAt(newC,index); + } + + /** pop the topmost RtfContainer from our stack */ + void popContainer() + { + m_containers.pop(); + } + + /* push an IBuilder to our stack / + void pushBuilder(IBuilder b) + { + m_builders.push(b); + }*/ + + /** pop the topmost IBuilder from our stack and return previous builder on stack + * @return null if builders stack is empty + + IBuilder popBuilderAndGetPreviousOne() + { + IBuilder result = null; + m_builders.pop(); + if(!m_builders.isEmpty()) { + result = (IBuilder)m_builders.peek(); + } + return result; + } + */ + /** return the current TableContext */ + TableContext getTableContext() + { + return (TableContext)m_tableContexts.peek(); + } + + /** push a TableContext to our stack */ + void pushTableContext(TableContext tc) + { + m_tableContexts.push(tc); + } + + /** pop a TableContext from our stack */ + void popTableContext() + { + m_tableContexts.pop(); + } +} \ No newline at end of file diff --git a/src/java/org/apache/fop/rtf/renderer/FoUnitsConverter.java b/src/java/org/apache/fop/rtf/renderer/FoUnitsConverter.java new file mode 100644 index 000000000..99bec8fd4 --- /dev/null +++ b/src/java/org/apache/fop/rtf/renderer/FoUnitsConverter.java @@ -0,0 +1,177 @@ +/* + * ============================================================================ + * 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; + +import java.util.*; + +//FOP +import org.apache.fop.apps.FOPException; + + +/** Converts XSL-FO units to RTF units + * + * @author Bertrand Delacretaz + * @author putzi + * @author Peter Herweg + * + * This class was originally developed by Bertrand Delacretaz bdelacretaz@codeconsult.ch + * for the JFOR project and is now integrated into FOP. + */ + +class FoUnitsConverter +{ + private static final FoUnitsConverter m_instance = new FoUnitsConverter(); + + /** points to twips: 1 twip is 1/20 of a point */ + public static final float POINT_TO_TWIPS = 20f; + + /** millimeters and centimeters to twips: , one point is 1/72 of an inch, one inch is 25.4 mm */ + public static final float IN_TO_TWIPS = 72f * POINT_TO_TWIPS; + public static final float MM_TO_TWIPS = IN_TO_TWIPS / 25.4f; + public static final float CM_TO_TWIPS = 10 * MM_TO_TWIPS; + + + /** conversion factors keyed by xsl:fo units names */ + private static final Map m_twipFactors = new HashMap(); + static { + m_twipFactors.put("mm",new Float(MM_TO_TWIPS)); + m_twipFactors.put("cm",new Float(CM_TO_TWIPS)); + m_twipFactors.put("pt",new Float(POINT_TO_TWIPS)); + m_twipFactors.put("in",new Float(IN_TO_TWIPS)); + } + + /** singleton pattern */ + private FoUnitsConverter() + { + } + + /** singleton pattern */ + static FoUnitsConverter getInstance() + { + return m_instance; + } + + /** convert given value to RTF units + * @param foValue a value like "12mm" + * TODO: tested with "mm" units only, needs work to comply with FO spec + * Why does it search for period instead of simply breaking last two + * Characters into another units string? - Chris + */ + float convertToTwips(String foValue) + throws FOPException + { + foValue = foValue.trim(); + + // break value into number and units + final StringBuffer number = new StringBuffer(); + final StringBuffer units = new StringBuffer(); + + for(int i=0; i < foValue.length(); i++) { + final char c = foValue.charAt(i); + if(Character.isDigit(c) || c == '.') { + number.append(c); + } else { + // found the end of the digits + units.append(foValue.substring(i).trim()); + break; + } + } + + return numberToTwips(number.toString(),units.toString()); + } + + + /** convert given value to twips according to given units */ + private float numberToTwips(String number,String units) + throws FOPException + { + float result = 0; + + // convert number to integer + try { + if(number != null && number.trim().length() > 0) { + result = Float.valueOf(number).floatValue(); + } + } catch(Exception e) { + throw new FOPException("number format error: cannot convert '" + number + "' to float value"); + } + + // find conversion factor + if(units != null && units.trim().length() > 0) { + final Float factor = (Float)m_twipFactors.get(units.toLowerCase()); + if(factor == null) throw new FOPException("conversion factor not found for '" + units + "' units"); + result *= factor.floatValue(); + } + + return result; + } + + /** convert a font size given in points like "12pt" */ + int convertFontSize(String size) + throws FOPException + { + size = size.trim(); + final String FONT_SUFFIX = "pt"; + if(!size.endsWith(FONT_SUFFIX)) { + throw new FOPException("Invalid font size '" + size + "', must end with '" + FONT_SUFFIX + "'"); + } + + float result = 0; + size = size.substring(0,size.length() - FONT_SUFFIX.length()); + try { + result = (Float.valueOf(size).floatValue()); + } catch(Exception e) { + throw new FOPException("Invalid font size value '" + size + "'"); + } + + // RTF font size units are in half-points + return (int)(result * 2.0); + } +} diff --git a/src/java/org/apache/fop/rtf/renderer/RTFHandler.java b/src/java/org/apache/fop/rtf/renderer/RTFHandler.java index 2de35ed58..cb38defab 100644 --- a/src/java/org/apache/fop/rtf/renderer/RTFHandler.java +++ b/src/java/org/apache/fop/rtf/renderer/RTFHandler.java @@ -55,7 +55,8 @@ import java.io.IOException; import java.io.OutputStream; import java.io.OutputStreamWriter; -import org.apache.fop.apps.Driver; +import org.apache.avalon.framework.logger.ConsoleLogger; +import org.apache.avalon.framework.logger.Logger; import org.apache.fop.apps.FOPException; import org.apache.fop.datatypes.ColorType; import org.apache.fop.fo.FOInputHandler; @@ -73,7 +74,9 @@ import org.apache.fop.fo.flow.TableRow; import org.apache.fop.fo.pagination.Flow; import org.apache.fop.fo.pagination.PageSequence; import org.apache.fop.fo.properties.Constants; +import org.apache.fop.fo.Property; import org.apache.fop.apps.Document; +import org.apache.fop.rtf.rtflib.rtfdoc.IRtfParagraphContainer; import org.apache.fop.rtf.rtflib.rtfdoc.RtfAttributes; import org.apache.fop.rtf.rtflib.rtfdoc.RtfColorTable; import org.apache.fop.rtf.rtflib.rtfdoc.RtfDocumentArea; @@ -81,22 +84,31 @@ import org.apache.fop.rtf.rtflib.rtfdoc.RtfFile; import org.apache.fop.rtf.rtflib.rtfdoc.RtfParagraph; import org.apache.fop.rtf.rtflib.rtfdoc.RtfSection; import org.apache.fop.rtf.rtflib.rtfdoc.RtfText; +import org.apache.fop.rtf.rtflib.rtfdoc.RtfTable; +import org.apache.fop.rtf.rtflib.rtfdoc.RtfTableRow; +import org.apache.fop.rtf.rtflib.rtfdoc.RtfTableCell; +import org.apache.fop.rtf.rtflib.rtfdoc.IRtfTableContainer; import org.xml.sax.SAXException; /** * RTF Handler: generates RTF output using the structure events from * the FO Tree sent to this structure handler. * - * @author bdelacretaz@apache.org + * @author Bertrand Delacretaz + * @author Trembicki-Guy, Ed + * @author Boris Poudérous + * @author Peter Herweg */ public class RTFHandler extends FOInputHandler { private RtfFile rtfFile; private final OutputStream os; + private final Logger log=new ConsoleLogger(); private RtfSection sect; private RtfDocumentArea docArea; private RtfParagraph para; private boolean warned = false; + private BuilderContext m_context=new BuilderContext(null); private static final String ALPHA_WARNING = "WARNING: RTF renderer is " + "veryveryalpha at this time, see class org.apache.fop.rtf.renderer.RTFHandler"; @@ -116,7 +128,7 @@ public class RTFHandler extends FOInputHandler { this.os = os; // use pdf fonts for now, this is only for resolving names org.apache.fop.render.pdf.FontSetup.setup(doc, null); - System.err.println(ALPHA_WARNING); + log.warn(ALPHA_WARNING); } /** @@ -151,12 +163,14 @@ public class RTFHandler extends FOInputHandler { public void startPageSequence(PageSequence pageSeq) { try { sect = docArea.newSection(); + m_context.pushContainer(sect); if (!warned) { sect.newParagraph().newText(ALPHA_WARNING); warned = true; } } catch (IOException ioe) { // FIXME could we throw Exception in all FOInputHandler events? + log.error("startPageSequence: " + ioe.getMessage()); throw new Error("IOException: " + ioe); } } @@ -165,6 +179,7 @@ public class RTFHandler extends FOInputHandler { * @see org.apache.fop.fo.FOInputHandler#endPageSequence(PageSequence) */ public void endPageSequence(PageSequence pageSeq) throws FOPException { + m_context.popContainer(); } /** @@ -190,11 +205,20 @@ public class RTFHandler extends FOInputHandler { attrBlockFontSize(bl, rtfAttr); attrBlockFontWeight(bl, rtfAttr); - para = sect.newParagraph(rtfAttr); + IRtfParagraphContainer pc=(IRtfParagraphContainer)m_context.getContainer(IRtfParagraphContainer.class,true,null); + para = pc.newParagraph(rtfAttr); + + m_context.pushContainer(para); } catch (IOException ioe) { // FIXME could we throw Exception in all FOInputHandler events? + log.error("startBlock: " + ioe.getMessage()); throw new Error("IOException: " + ioe); } + catch(Exception e) + { + log.error("startBlock: " + e.getMessage()); + throw new Error("Exception: " + e); + } } @@ -202,18 +226,65 @@ public class RTFHandler extends FOInputHandler { * @see org.apache.fop.fo.FOInputHandler#endBlock(Block) */ public void endBlock(Block bl) { + m_context.popContainer(); } /** * @see org.apache.fop.fo.FOInputHandler#startTable(Table) */ public void startTable(Table tbl) { + // create an RtfTable in the current table container + TableContext tableContext = new TableContext(m_context); + RtfAttributes atts=new RtfAttributes(); + + try + { + final IRtfTableContainer tc = (IRtfTableContainer)m_context.getContainer(IRtfTableContainer.class,true,null); + m_context.pushContainer(tc.newTable(atts, tableContext)); + } + catch(Exception e) + { + log.error("startTable:" + e.getMessage()); + throw new Error(e.getMessage()); + } + + m_context.pushTableContext(tableContext); } /** * @see org.apache.fop.fo.FOInputHandler#endTable(Table) */ public void endTable(Table tbl) { + m_context.popTableContext(); + m_context.popContainer(); + } + + /** + * + * @param th TableColumn that is starting; + */ + + public void startColumn(TableColumn tc) { + try + { + Integer iWidth=new Integer(tc.getColumnWidth()/1000); + m_context.getTableContext().setNextColumnWidth(iWidth.toString()+"pt"); + m_context.getTableContext().setNextColumnRowSpanning(new Integer(0),null); + } + catch(Exception e) + { + log.error("startColumn: " + e.getMessage()); + throw new Error(e.getMessage()); + } + + } + + /** + * + * @param th TableColumn that is ending; + */ + + public void endColumn(TableColumn tc){ } /** @@ -244,50 +315,124 @@ public class RTFHandler extends FOInputHandler { * @see org.apache.fop.fo.FOInputHandler#startBody(TableBody) */ public void startBody(TableBody tb) { + try + { + RtfAttributes atts=TableAttributesConverter.convertRowAttributes (tb.properties, null, null); + + RtfTable tbl = (RtfTable)m_context.getContainer(RtfTable.class,true,this); + tbl.setHeaderAttribs(atts); + } + catch(Exception e) + { + log.error("startBody: " + e.getMessage()); + throw new Error(e.getMessage()); + } } /** * @see org.apache.fop.fo.FOInputHandler#endBody(TableBody) */ public void endBody(TableBody tb) { - } - - /** - * - * @param tc TableColumn that is starting; - */ - public void startColumn(TableColumn tc) { - } - - /** - * - * @param tc TableColumn that is ending; - */ - public void endColumn(TableColumn tc) { + try + { + RtfTable tbl = (RtfTable)m_context.getContainer(RtfTable.class,true,this); + tbl.setHeaderAttribs( null ); + } + catch(Exception e) + { + log.error("endBody: " + e.getMessage()); + throw new Error(e.getMessage()); + } } /** * @see org.apache.fop.fo.FOInputHandler#startRow(TableRow) */ public void startRow(TableRow tr) { + try + { + // create an RtfTableRow in the current RtfTable + final RtfTable tbl = (RtfTable)m_context.getContainer(RtfTable.class,true,null); + + RtfAttributes tblAttribs = tbl.getRtfAttributes(); + RtfAttributes tblRowAttribs = new RtfAttributes(); + RtfAttributes atts=TableAttributesConverter.convertRowAttributes(tr.properties,null,tbl.getHeaderAttribs()); + + m_context.pushContainer(tbl.newTableRow( atts )); + + // reset column iteration index to correctly access column widths + m_context.getTableContext().selectFirstColumn(); + } + catch(Exception e) + { + log.error("startRow: " + e.getMessage()); + throw new Error(e.getMessage()); + } } /** * @see org.apache.fop.fo.FOInputHandler#endRow(TableRow) */ public void endRow(TableRow tr) { + m_context.popContainer(); + m_context.getTableContext().decreaseRowSpannings(); } /** * @see org.apache.fop.fo.FOInputHandler#startCell(TableCell) */ public void startCell(TableCell tc) { + try + { + TableContext tctx=m_context.getTableContext(); + final RtfTableRow row = (RtfTableRow)m_context.getContainer(RtfTableRow.class,true,null); + + + //while the current column is in row-spanning, act as if + //a vertical merged cell would have been specified. + while(tctx.getNumberOfColumns()>tctx.getColumnIndex() && tctx.getColumnRowSpanningNumber().intValue()>0) + { + row.newTableCellMergedVertically((int)tctx.getColumnWidth(),tctx.getColumnRowSpanningAttrs()); + tctx.selectNextColumn(); + } + + //get the width of the currently started cell + float width=tctx.getColumnWidth(); + + // create an RtfTableCell in the current RtfTableRow + RtfAttributes atts=TableAttributesConverter.convertCellAttributes(tc.properties,null); + RtfTableCell cell=row.newTableCell((int)width, atts); + + //process number-rows-spanned attribute + Property p=null; + if ((p=tc.properties.get("number-rows-spanned")) != null && false) + { + // Start vertical merge + cell.setVMerge(RtfTableCell.MERGE_START); + + // set the number of rows spanned + tctx.setCurrentColumnRowSpanning(new Integer(p.getNumber().intValue()), cell.getRtfAttributes()); + } + else + { + tctx.setCurrentColumnRowSpanning(new Integer(1),null); + } + + m_context.pushContainer(cell); + } + catch(Exception e) + { + log.error("startCell: " + e.getMessage()); + throw new Error(e.getMessage()); + } } /** * @see org.apache.fop.fo.FOInputHandler#endCell(TableCell) */ public void endCell(TableCell tc) { + m_context.popContainer(); + m_context.getTableContext().selectNextColumn(); } // Lists @@ -414,6 +559,7 @@ public class RTFHandler extends FOInputHandler { para.newText(new String(data, start, length)); } catch (IOException ioe) { // FIXME could we throw Exception in all FOInputHandler events? + log.error("characters: " + ioe.getMessage()); throw new Error("IOException: " + ioe); } } @@ -468,6 +614,8 @@ public class RTFHandler extends FOInputHandler { if ((fopValue.getRed() == 0) && (fopValue.getGreen() == 0) && (fopValue.getBlue() == 0) && (fopValue.getAlpha() == 0)) { rtfColor = RtfColorTable.getInstance().getColorNumber("white").intValue(); + currentRTFBackgroundColor = -1; + return; } else { rtfColor = convertFOPColorToRTF(fopValue); } diff --git a/src/java/org/apache/fop/rtf/renderer/TableAttributesConverter.java b/src/java/org/apache/fop/rtf/renderer/TableAttributesConverter.java new file mode 100644 index 000000000..49f7bb669 --- /dev/null +++ b/src/java/org/apache/fop/rtf/renderer/TableAttributesConverter.java @@ -0,0 +1,440 @@ +/* + * ============================================================================ + * 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; + +//RTF +import org.apache.fop.rtf.rtflib.rtfdoc.BorderAttributesConverter; + +//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.ColorTypeProperty; +import org.apache.fop.fo.NumberProperty; +import org.apache.fop.datatypes.ColorType; + +import org.xml.sax.Attributes; +import org.apache.fop.rtf.rtflib.rtfdoc.RtfAttributes; +import org.apache.fop.rtf.rtflib.rtfdoc.ITableAttributes; +import org.apache.fop.rtf.rtflib.rtfdoc.RtfColorTable; + +/** + * Contributor(s): + * @author Roberto Marra + * @author Boris Poudérous + * @author Normand Massé + * @author Peter Herweg + * + * This class was originally developed for the JFOR project and + * is now integrated into FOP. +-----------------------------------------------------------------------------*/ + +/** + * Provides methods to convert the attributes to RtfAttributes. + */ + +public class TableAttributesConverter { + + static Logger log=new ConsoleLogger(); + + ////////////////////////////////////////////////// + // @@ Construction + ////////////////////////////////////////////////// + + /** + * Constructor. + */ + private TableAttributesConverter() { + } + + ////////////////////////////////////////////////// + // @@ Static converter methods + ////////////////////////////////////////////////// + + + /** + * Converts cell attributes to rtf attributes. + * @param attrs Given attributes + * @param defaultAttributes Default rtf attributes + * + * @return All valid rtf attributes together + * + * @throws ConverterException On convertion error + */ + static RtfAttributes convertCellAttributes(PropertyList props, PropertyList defProps) + throws FOPException { + + Property p; + EnumProperty ep; + RtfColorTable colorTable=RtfColorTable.getInstance(); + + RtfAttributes attrib=null; + + if(defProps!=null) + { + attrib=convertCellAttributes(defProps,null); + } + else + { + attrib=new RtfAttributes(); + } + + boolean isBorderPresent=false; + + // Cell background color + if ((p=props.getNearestSpecified("background-color"))!=null) + { + ColorType color=p.getColorType(); + if(color!=null) + { + if(color.getAlpha()!=0 + || color.getRed()!=0 + || color.getGreen()!=0 + || color.getBlue()!=0) + { + attrib.set( + ITableAttributes.CELL_COLOR_BACKGROUND, + RTFHandler.convertFOPColorToRTF(color)); + } + } + else + { + log.warn("Named color '" + p.toString() + "' not found. "); + } + + } + + // Cell borders : + if ((p=props.getExplicit("border-color"))!=null){ + ListProperty listprop=(ListProperty)p; + ColorType color=null; + if(listprop.getList().get(0) instanceof NCnameProperty){ + color=new ColorType(((NCnameProperty)listprop.getList().get(0)).getNCname()); + } + else if(listprop.getList().get(0) instanceof ColorTypeProperty){ + color=((ColorTypeProperty)listprop.getList().get(0)).getColorType(); + } + + attrib.set( + BorderAttributesConverter.BORDER_COLOR, + colorTable.getColorNumber((int)color.getRed(),(int)color.getGreen(),(int)color.getBlue()).intValue()); + } + if ((p=props.getExplicit("border-top-color"))!=null){ + ColorType color=p.getColorType(); + attrib.set( + BorderAttributesConverter.BORDER_COLOR, + colorTable.getColorNumber((int)color.getRed(),(int)color.getGreen(),(int)color.getBlue()).intValue()); + } + if((p=props.getExplicit("border-bottom-color"))!=null){ + ColorType color=p.getColorType(); + attrib.set( + BorderAttributesConverter.BORDER_COLOR, + colorTable.getColorNumber((int)color.getRed(),(int)color.getGreen(),(int)color.getBlue()).intValue()); + } + if((p=props.getExplicit("border-left-color"))!=null){ + ColorType color=p.getColorType(); + attrib.set( + BorderAttributesConverter.BORDER_COLOR, + colorTable.getColorNumber((int)color.getRed(),(int)color.getGreen(),(int)color.getBlue()).intValue()); + } + if((p=props.getExplicit("border-right-color"))!=null){ + ColorType color=p.getColorType(); + attrib.set( + BorderAttributesConverter.BORDER_COLOR, + colorTable.getColorNumber((int)color.getRed(),(int)color.getGreen(),(int)color.getBlue()).intValue()); + } + + // Border styles do not inherit from parent + if((p=props.get("border-style"))!=null){ + log.warn("border-style not implemented. Please use border-style-left, ...-right, ...-top or ...-bottom"); + /* + attrib.set(ITableAttributes.CELL_BORDER_LEFT, "\\"+convertAttributetoRtf(e.getEnum())); + attrib.set(ITableAttributes.CELL_BORDER_RIGHT, "\\"+convertAttributetoRtf(e.getEnum())); + attrib.set(ITableAttributes.CELL_BORDER_BOTTOM,"\\"+convertAttributetoRtf(e.getEnum())); + attrib.set(ITableAttributes.CELL_BORDER_TOP, "\\"+convertAttributetoRtf(e.getEnum())); + isBorderPresent=true; + */ + } + ep=(EnumProperty)props.get("border-top-style"); + if(ep!=null && ep.getEnum()!=Constants.NONE){ + attrib.set(ITableAttributes.CELL_BORDER_TOP, "\\"+convertAttributetoRtf(ep.getEnum())); + isBorderPresent=true; + } + ep=(EnumProperty)props.get("border-bottom-style"); + if(ep!=null && ep.getEnum()!=Constants.NONE){ + attrib.set(ITableAttributes.CELL_BORDER_BOTTOM,"\\"+convertAttributetoRtf(ep.getEnum())); + isBorderPresent=true; + } + ep=(EnumProperty)props.get("border-left-style"); + if(ep!=null && ep.getEnum()!=Constants.NONE){ + attrib.set(ITableAttributes.CELL_BORDER_LEFT, "\\"+convertAttributetoRtf(ep.getEnum())); + isBorderPresent=true; + } + ep=(EnumProperty)props.get("border-right-style"); + if(ep!=null && ep.getEnum()!=Constants.NONE){ + attrib.set(ITableAttributes.CELL_BORDER_RIGHT, "\\"+convertAttributetoRtf(ep.getEnum())); + isBorderPresent=true; + } + + if((p=props.get("border-width"))!=null) { + ListProperty listprop=(ListProperty)p; + LengthProperty lengthprop=(LengthProperty)listprop.getList().get(0); + + Float f=new Float(lengthprop.getLength().getValue()/1000f); + String sValue = f.toString() + "pt"; + + attrib.set(BorderAttributesConverter.BORDER_WIDTH, (int)FoUnitsConverter.getInstance().convertToTwips(sValue)); + } + else if(isBorderPresent){ + //if not defined, set default border width + //note 20 twips = 1 point + attrib.set(BorderAttributesConverter.BORDER_WIDTH, (int)FoUnitsConverter.getInstance().convertToTwips("1pt")); + } + + + // Column spanning : + NumberProperty n=(NumberProperty)props.get("number-columns-spanned"); + if(n!=null && n.getNumber().intValue()>1) { + attrib.set(ITableAttributes.COLUMN_SPAN, n.getNumber().intValue()); + } + + return attrib; + } + + + /** + * Converts table and row attributes to rtf attributes. + * + * @param attrs Given attributes + * @param defaultAttributes Default rtf attributes + * + * @return All valid rtf attributes together + * + * @throws ConverterException On convertion error + */ + static RtfAttributes convertRowAttributes(PropertyList props, PropertyList defProps, RtfAttributes rtfatts) + throws FOPException { + + Property p; + EnumProperty ep; + RtfColorTable colorTable=RtfColorTable.getInstance(); + + RtfAttributes attrib=null; + + if(defProps!=null) + { + attrib=convertRowAttributes(defProps,null,rtfatts); + } + else + { + if(rtfatts==null) + attrib=new RtfAttributes(); + else + attrib=rtfatts; + } + + String attrValue; + boolean isBorderPresent=false; + //need to set a default width + + //check for keep-together row attribute + if ((p=props.get("keep-together.within-page"))!=null){ + attrib.set(ITableAttributes.ROW_KEEP_TOGETHER); + } + + if ((p=props.get("keep-together"))!=null){ + attrib.set(ITableAttributes.ROW_KEEP_TOGETHER); + } + + //Check for keep-with-next row attribute. + if ((p=props.get("keep-together"))!=null){ + attrib.set(ITableAttributes.ROW_KEEP_WITH_NEXT); + } + + //Check for keep-with-previous row attribute. + if ((p=props.get("keep-with-previous"))!=null){ + attrib.set(ITableAttributes.ROW_KEEP_WITH_PREVIOUS); + } + + //Check for height row attribute. + if ((p=props.get("height"))!=null){ + Float f=new Float(p.getLength().getValue()/1000); + attrValue = f.toString() + "pt"; + attrib.set(ITableAttributes.ROW_HEIGHT, (int)FoUnitsConverter.getInstance().convertToTwips(attrValue)); + } + + /* to write a border to a side of a cell one must write the directional side (ie. left, right) and the inside value + * if one needs to be taken out ie if the cell lies on the edge of a table or not, the offending value will be taken out + * by RtfTableRow. This is because you can't say BORDER_TOP and BORDER_HORIZONTAL if the cell lies at the + * top of the table. Similarly using BORDER_BOTTOM and BORDER_HORIZONTAL will not work if the cell lies at th + * bottom of the table. The same rules apply for left right and vertical. + + * Also, the border type must be written after every control word. Thus it is implemented that the border type is the value + * of the border place. + */ + if((p=props.get("border-style"))!=null){ + log.warn("border-style not implemented. Please use border-style-left, ...-right, ...-top or ...-bottom"); + +// attrValue = new String(AbstractBuilder.getValue( attrs, "border-style", defAttrs )); +// attrib.set(ITableAttributes.ROW_BORDER_LEFT,"\\"+BorderAttributesConverter.convertAttributetoRtf(attrValue)); +// attrib.set(ITableAttributes.ROW_BORDER_RIGHT,"\\"+BorderAttributesConverter.convertAttributetoRtf(attrValue)); +// attrib.set(ITableAttributes.ROW_BORDER_HORIZONTAL,"\\"+BorderAttributesConverter.convertAttributetoRtf(attrValue)); +// attrib.set(ITableAttributes.ROW_BORDER_VERTICAL,"\\"+BorderAttributesConverter.convertAttributetoRtf(attrValue)); +// attrib.set(ITableAttributes.ROW_BORDER_BOTTOM,"\\"+BorderAttributesConverter.convertAttributetoRtf(attrValue)); +// attrib.set(ITableAttributes.ROW_BORDER_TOP,"\\"+BorderAttributesConverter.convertAttributetoRtf(attrValue)); +// isBorderPresent=true; + } + ep=(EnumProperty)props.get("border-top-style"); + if(ep!=null && ep.getEnum()!=Constants.NONE){ + attrib.set(ITableAttributes.ROW_BORDER_TOP, "\\"+convertAttributetoRtf(ep.getEnum())); + attrib.set(ITableAttributes.ROW_BORDER_HORIZONTAL,"\\"+convertAttributetoRtf(ep.getEnum())); + isBorderPresent=true; + } + ep=(EnumProperty)props.get("border-bottom-style"); + if(ep!=null && ep.getEnum()!=Constants.NONE){ + attrib.set(ITableAttributes.ROW_BORDER_BOTTOM, "\\"+convertAttributetoRtf(ep.getEnum())); + attrib.set(ITableAttributes.ROW_BORDER_HORIZONTAL,"\\"+convertAttributetoRtf(ep.getEnum())); + isBorderPresent=true; + } + ep=(EnumProperty)props.get("border-left-style"); + if(ep!=null && ep.getEnum()!=Constants.NONE){ + attrib.set(ITableAttributes.ROW_BORDER_LEFT, "\\"+convertAttributetoRtf(ep.getEnum())); + attrib.set(ITableAttributes.ROW_BORDER_VERTICAL, "\\"+convertAttributetoRtf(ep.getEnum())); + isBorderPresent=true; + } + ep=(EnumProperty)props.get("border-right-style"); + if(ep!=null && ep.getEnum()!=Constants.NONE){ + attrib.set(ITableAttributes.ROW_BORDER_RIGHT, "\\"+convertAttributetoRtf(ep.getEnum())); + attrib.set(ITableAttributes.ROW_BORDER_VERTICAL, "\\"+convertAttributetoRtf(ep.getEnum())); + isBorderPresent=true; + } + ep=(EnumProperty)props.get("border-horizontal-style"); + if(ep!=null && ep.getEnum()!=Constants.NONE){ + attrib.set(ITableAttributes.ROW_BORDER_HORIZONTAL, "\\"+convertAttributetoRtf(ep.getEnum())); + attrib.set(ITableAttributes.ROW_BORDER_TOP, "\\"+convertAttributetoRtf(ep.getEnum())); + attrib.set(ITableAttributes.ROW_BORDER_BOTTOM, "\\"+convertAttributetoRtf(ep.getEnum())); + isBorderPresent=true; + } + ep=(EnumProperty)props.get("border-vertical-style"); + if(ep!=null && ep.getEnum()!=Constants.NONE){ + attrib.set(ITableAttributes.ROW_BORDER_VERTICAL, "\\"+convertAttributetoRtf(ep.getEnum())); + attrib.set(ITableAttributes.ROW_BORDER_LEFT, "\\"+convertAttributetoRtf(ep.getEnum())); + attrib.set(ITableAttributes.ROW_BORDER_RIGHT, "\\"+convertAttributetoRtf(ep.getEnum())); + isBorderPresent=true; + } + + if((p=props.get("border-width"))!=null){ + ListProperty listprop=(ListProperty)p; + LengthProperty lengthprop=(LengthProperty)listprop.getList().get(0); + + Float f=new Float(lengthprop.getLength().getValue()/1000f); + String sValue = f.toString() + "pt"; + + attrib.set(BorderAttributesConverter.BORDER_WIDTH, (int)FoUnitsConverter.getInstance().convertToTwips(sValue)); + } + else if(isBorderPresent){ + //if not defined, set default border width + //note 20 twips = 1 point + attrib.set(BorderAttributesConverter.BORDER_WIDTH, (int)FoUnitsConverter.getInstance().convertToTwips("1pt")); + } + + return attrib; + } + + + + public static String convertAttributetoRtf(int iBorderStyle) { + // Added by Normand Masse + // "solid" is interpreted like "thin" + if (iBorderStyle==Constants.SOLID) { + return BorderAttributesConverter.BORDER_SINGLE_THICKNESS; +/* } else if (iBorderStyle==Constants.THIN) { + return BorderAttributesConverter.BORDER_SINGLE_THICKNESS; + } else if (iBorderStyle==Constants.THICK) { + return BorderAttributesConverter.BORDER_DOUBLE_THICKNESS; + } else if (iBorderStyle==Constants. value.equals("shadowed")) { + return BorderAttributesConverter.BORDER_SHADOWED;*/ + } else if (iBorderStyle==Constants.DOUBLE) { + return BorderAttributesConverter.BORDER_DOUBLE; + } else if (iBorderStyle==Constants.DOTTED) { + return BorderAttributesConverter.BORDER_DOTTED; + } else if (iBorderStyle==Constants.DASHED) { + return BorderAttributesConverter.BORDER_DASH; +/* } else if (iBorderStyle==Constants value.equals("hairline")) { + return BorderAttributesConverter.BORDER_HAIRLINE;*/ +/* } else if (iBorderStyle==Constant value.equals("dot-dash")) { + return BorderAttributesConverter.BORDER_DOT_DASH; + } else if (iBorderStyle==Constant value.equals("dot-dot-dash")) { + return BorderAttributesConverter.BORDER_DOT_DOT_DASH; + } else if (iBorderStyle==Constant value.equals("triple")) { + return BorderAttributesConverter.BORDER_TRIPLE; + } else if (iBorderStyle==Constant value.equals("wavy")) { + return BorderAttributesConverter.BORDER_WAVY; + } else if (iBorderStyle==Constant value.equals("wavy-double")) { + return BorderAttributesConverter.BORDER_WAVY_DOUBLE; + } else if (iBorderStyle==Constant value.equals("striped")) { + return BorderAttributesConverter.BORDER_STRIPED; + } else if (iBorderStyle==Constant value.equals("emboss")) { + return BorderAttributesConverter.BORDER_EMBOSS; + } else if (iBorderStyle==Constant value.equals("engrave")) { + return BorderAttributesConverter.BORDER_ENGRAVE;*/ + } else { + return null; + } + } + +} \ No newline at end of file diff --git a/src/java/org/apache/fop/rtf/renderer/TableContext.java b/src/java/org/apache/fop/rtf/renderer/TableContext.java new file mode 100644 index 000000000..088da98a9 --- /dev/null +++ b/src/java/org/apache/fop/rtf/renderer/TableContext.java @@ -0,0 +1,224 @@ +/* + * ============================================================================ + * 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; + +import java.util.*; + +import org.apache.avalon.framework.logger.ConsoleLogger; +import org.apache.avalon.framework.logger.Logger; +import org.apache.fop.rtf.rtflib.rtfdoc.RtfAttributes; +import org.apache.fop.rtf.rtflib.interfaces.ITableColumnsInfo; + + +/** Used when handling fo:table to hold information to build the table. + * + * Contributor(s): + * @author Bertrand Delacretaz + * @author Trembicki-Guy, Ed + * @author Boris Poudérous + * @author Peter Herweg + * + * This class was originally developed for the JFOR project and + * is now integrated into FOP. + */ + +class TableContext implements ITableColumnsInfo +{ + private final Logger log=new ConsoleLogger(); + private final BuilderContext m_context; + private final ArrayList m_colWidths = new ArrayList(); + private int m_colIndex; + + /** + * Added by Peter Herweg on 2002-06-29 + * This ArrayList contains one element for each column in the table. + * value == 0 means there is no row-spanning + * value > 0 means there is row-spanning + * Each value in the list is decreased by 1 after each finished table-row + */ + private final ArrayList m_colRowSpanningNumber = new ArrayList(); + + /** + * Added by Peter Herweg on 2002-06-29 + * If there has a vertical merged cell to be created, its attributes are + * inherited from the corresponding MERGE_START-cell. + * For this purpose the attributes of a cell are stored in this array, as soon + * as a number-rows-spanned attribute has been found. + */ + private final ArrayList m_colRowSpanningAttrs = new ArrayList(); //Added by Peter Herweg on 2002-06-29 + + private boolean m_bNextRowBelongsToHeader=false; + + public void setNextRowBelongsToHeader(boolean bNextRowBelongsToHeader) + { + m_bNextRowBelongsToHeader=bNextRowBelongsToHeader; + } + + public boolean getNextRowBelongsToHeader() + { + return m_bNextRowBelongsToHeader; + } + + TableContext(BuilderContext ctx) + { + m_context = ctx; + } + + void setNextColumnWidth(String strWidth) + throws Exception + { + + m_colWidths.add( new Float(FoUnitsConverter.getInstance().convertToTwips(strWidth))); + } + + //Added by Peter Herweg on 2002-06-29 + RtfAttributes getColumnRowSpanningAttrs() + { + return (RtfAttributes)m_colRowSpanningAttrs.get(m_colIndex); + } + + //Added by Peter Herweg on 2002-06-29 + Integer getColumnRowSpanningNumber() + { + return (Integer)m_colRowSpanningNumber.get(m_colIndex); + } + + //Added by Peter Herweg on 2002-06-29 + void setCurrentColumnRowSpanning(Integer iRowSpanning, RtfAttributes attrs) + throws Exception + { + + if(m_colIndex0) + i=new Integer(i.intValue()-1); + + m_colRowSpanningNumber.set(z,i); + + if(i.intValue()==0) + m_colRowSpanningAttrs.set(z,null); + } + } + + /** reset the column iteration index, meant to be called when creating a new row + * The 'public' modifier has been added by Boris Poudérous for 'number-columns-spanned' processing + */ + public void selectFirstColumn() + { + m_colIndex = 0; + } + + /** increment the column iteration index + * The 'public' modifier has been added by Boris Poudérous for 'number-columns-spanned' processing + */ + public void selectNextColumn() + { + m_colIndex++; + } + + /** get current column width according to column iteration index + * @return INVALID_COLUMN_WIDTH if we cannot find the value + * The 'public' modifier has been added by Boris Poudérous for 'number-columns-spanned' processing + */ + public float getColumnWidth() + { + try { + return ((Float)m_colWidths.get(m_colIndex)).floatValue(); + } catch (IndexOutOfBoundsException ex) { + // this code contributed by Trembicki-Guy, Ed + log.warn("fo:table-column width not defined, using " + INVALID_COLUM_WIDTH); + return INVALID_COLUM_WIDTH; + } + } + + /** Added by Boris Poudérous on 07/22/2002 */ + public int getColumnIndex() + { + return m_colIndex; + } + /** - end - */ + + /** Added by Boris Poudérous on 07/22/2002 */ + public int getNumberOfColumns() + { + return m_colWidths.size(); + } + /** - end - */ +} + diff --git a/src/java/org/apache/fop/rtf/rtflib/rtfdoc/ITableAttributes.java b/src/java/org/apache/fop/rtf/rtflib/rtfdoc/ITableAttributes.java index c3d1a2d5f..6314e303a 100644 --- a/src/java/org/apache/fop/rtf/rtflib/rtfdoc/ITableAttributes.java +++ b/src/java/org/apache/fop/rtf/rtflib/rtfdoc/ITableAttributes.java @@ -152,6 +152,7 @@ public interface ITableAttributes { //Table row attributes /** row attribute, keep-together */ public static final String ROW_KEEP_TOGETHER = "trkeep"; + public static final String ROW_HEIGHT = "trrh"; /** * This control word is nonexistent in RTF, used to simulate the diff --git a/src/java/org/apache/fop/rtf/rtflib/rtfdoc/RtfTable.java b/src/java/org/apache/fop/rtf/rtflib/rtfdoc/RtfTable.java index be05e4c77..a874dc21a 100755 --- a/src/java/org/apache/fop/rtf/rtflib/rtfdoc/RtfTable.java +++ b/src/java/org/apache/fop/rtf/rtflib/rtfdoc/RtfTable.java @@ -176,6 +176,10 @@ public class RtfTable extends RtfContainer { headerAttribs = attrs; } + public RtfAttributes getHeaderAttribs() { + return headerAttribs; + } + /** * Added by Normand Masse * @return the table-header attributes if they are present, otherwise the