From: Jeremias Maerki Date: Sun, 6 Jul 2008 15:09:10 +0000 (+0000) Subject: Bugzilla #43606: X-Git-Tag: fop-0_95~21 X-Git-Url: https://source.dussan.org/?a=commitdiff_plain;h=3d4f3b575e83998467d6e3ab13403c0ebaa1f53a;p=xmlgraphics-fop.git Bugzilla #43606: column-width accepts percent values (proportional-column-width and % working) Table width accepts percent values (100% of the page width as standard) Nested tables are working It is also possible to make nested tables with a higher depth than 3 without causing word to crash Submitted by: Maximilan Aster Changes to the patch by Jeremias: - Patch simplified (reuse of ColumnSetup from the layoutmgr package) - Percentages and proportional-column-width didn't work properly in my tests -> fixed - Adjustments for FOP code conventions Bugzilla #43824: page-number-citation working but has to be refreshed inside word to show the correct values Submitted by: Maximilan Aster Changes to the patch by Jeremias: - Adjustments for FOP code conventions git-svn-id: https://svn.apache.org/repos/asf/xmlgraphics/fop/branches/fop-0_95@674304 13f79535-47bb-0310-9956-ffa450edef68 --- diff --git a/src/java/org/apache/fop/layoutmgr/table/ColumnSetup.java b/src/java/org/apache/fop/layoutmgr/table/ColumnSetup.java index 2ef2be908..b3ffb4d30 100644 --- a/src/java/org/apache/fop/layoutmgr/table/ColumnSetup.java +++ b/src/java/org/apache/fop/layoutmgr/table/ColumnSetup.java @@ -25,9 +25,9 @@ import java.util.ListIterator; import org.apache.commons.logging.Log; import org.apache.commons.logging.LogFactory; -import org.apache.fop.datatypes.PercentBaseContext; -import org.apache.fop.datatypes.Length; +import org.apache.fop.datatypes.Length; +import org.apache.fop.datatypes.PercentBaseContext; import org.apache.fop.fo.FONode; import org.apache.fop.fo.flow.table.Table; import org.apache.fop.fo.flow.table.TableColumn; @@ -44,9 +44,9 @@ public class ColumnSetup { private Table table; private List columns = new java.util.ArrayList(); private List colWidths = new java.util.ArrayList(); - + private int maxColIndexReferenced = 0; - + /** * Main Constructor. * @param table the table to construct this column setup for @@ -56,7 +56,7 @@ public class ColumnSetup { prepareColumns(); initializeColumnWidths(); } - + private void prepareColumns() { List rawCols = table.getColumns(); if (rawCols != null) { @@ -119,7 +119,7 @@ public class ColumnSetup { return (TableColumn) columns.get(index - 1); } } - + /** {@inheritDoc} */ public String toString() { return columns.toString(); @@ -133,15 +133,15 @@ public class ColumnSetup { return columns.size(); } } - + /** @return an Iterator over all columns */ public Iterator iterator() { return this.columns.iterator(); } - + /* private void createColumnsFromFirstRow() { - //TODO Create oldColumns from first row here + //TODO Create oldColumns from first row here //--> rule 2 in "fixed table layout", see CSS2, 17.5.2 //Alternative: extend oldColumns on-the-fly, but in this case we need the //new property evaluation context so proportional-column-width() works @@ -154,13 +154,13 @@ public class ColumnSetup { /** * Initializes the column's widths - * + * */ private void initializeColumnWidths() { - + TableColumn col; Length colWidth; - + for (int i = columns.size(); --i >= 0;) { if (columns.get(i) != null) { col = (TableColumn) columns.get(i); @@ -170,49 +170,60 @@ public class ColumnSetup { } colWidths.add(0, null); } - + /** * Works out the base unit for resolving proportional-column-width() * [p-c-w(x) = x * base_unit_ipd] - * + * * @param tlm the TableLayoutManager * @return the computed base unit (in millipoint) */ protected double computeTableUnit(TableLayoutManager tlm) { - + return computeTableUnit(tlm, tlm.getContentAreaIPD()); + } + + /** + * Works out the base unit for resolving proportional-column-width() + * [p-c-w(x) = x * base_unit_ipd] + * + * @param percentBaseContext the percent base context for relative values + * @param contentAreaIPD the IPD of the available content area + * @return the computed base unit (in millipoints) + */ + public float computeTableUnit(PercentBaseContext percentBaseContext, int contentAreaIPD) { + int sumCols = 0; float factors = 0; - double unit = 0; - - /* calculate the total width (specified absolute/percentages), + float unit = 0; + + /* calculate the total width (specified absolute/percentages), * and work out the total number of factors to use to distribute * the remaining space (if any) */ for (Iterator i = colWidths.iterator(); i.hasNext();) { Length colWidth = (Length) i.next(); if (colWidth != null) { - sumCols += colWidth.getValue(tlm); + sumCols += colWidth.getValue(percentBaseContext); if (colWidth instanceof TableColLength) { - factors += - ((TableColLength) colWidth).getTableUnits(); + factors += ((TableColLength) colWidth).getTableUnits(); } } } - - /* distribute the remaining space over the accumulated - * factors (if any) + + /* distribute the remaining space over the accumulated + * factors (if any) */ if (factors > 0) { - if (sumCols < tlm.getContentAreaIPD()) { - unit = (tlm.getContentAreaIPD() - sumCols) / factors; + if (sumCols < contentAreaIPD) { + unit = (contentAreaIPD - sumCols) / factors; } else { log.warn("No space remaining to distribute over columns."); } } - + return unit; } - + /** * @param col column index (1 is first column) * @param context the context for percentage based calculations @@ -252,5 +263,5 @@ public class ColumnSetup { } return sum; } - + } diff --git a/src/java/org/apache/fop/render/rtf/FoUnitsConverter.java b/src/java/org/apache/fop/render/rtf/FoUnitsConverter.java index fa95b8502..33a2ff904 100644 --- a/src/java/org/apache/fop/render/rtf/FoUnitsConverter.java +++ b/src/java/org/apache/fop/render/rtf/FoUnitsConverter.java @@ -5,9 +5,9 @@ * The ASF licenses this file to You under the Apache License, Version 2.0 * (the "License"); you may not use this file except in compliance with * the License. You may obtain a copy of the License at - * + * * http://www.apache.org/licenses/LICENSE-2.0 - * + * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. @@ -19,10 +19,9 @@ package org.apache.fop.render.rtf; -import java.util.Map; import java.util.HashMap; +import java.util.Map; -//FOP import org.apache.fop.apps.FOPException; import org.apache.fop.fo.properties.FixedLength; @@ -143,4 +142,8 @@ final class FoUnitsConverter { // RTF font size units are in half-points return (int)(result * 2.0); } + + public float convertMptToTwips(int width) { + return width * POINT_TO_TWIPS / 1000; + } } diff --git a/src/java/org/apache/fop/render/rtf/PageAttributesConverter.java b/src/java/org/apache/fop/render/rtf/PageAttributesConverter.java index 50355e145..d50a81656 100644 --- a/src/java/org/apache/fop/render/rtf/PageAttributesConverter.java +++ b/src/java/org/apache/fop/render/rtf/PageAttributesConverter.java @@ -5,9 +5,9 @@ * The ASF licenses this file to You under the Apache License, Version 2.0 * (the "License"); you may not use this file except in compliance with * the License. You may obtain a copy of the License at - * + * * http://www.apache.org/licenses/LICENSE-2.0 - * + * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. @@ -21,6 +21,7 @@ package org.apache.fop.render.rtf; import org.apache.commons.logging.Log; import org.apache.commons.logging.impl.SimpleLog; + import org.apache.fop.datatypes.Length; import org.apache.fop.fo.Constants; import org.apache.fop.fo.expr.NumericOp; @@ -46,19 +47,21 @@ final class PageAttributesConverter { */ private PageAttributesConverter() { } - + /** convert xsl:fo attributes to RTF text attributes */ static RtfAttributes convertPageAttributes(SimplePageMaster pagemaster) { FOPRtfAttributes attrib = new FOPRtfAttributes(); - + try { RegionBA before = (RegionBA) pagemaster.getRegion(Constants.FO_REGION_BEFORE); RegionBody body = (RegionBody) pagemaster.getRegion(Constants.FO_REGION_BODY); RegionBA after = (RegionBA) pagemaster.getRegion(Constants.FO_REGION_AFTER); - + attrib.setTwips(RtfPage.PAGE_WIDTH, pagemaster.getPageWidth()); attrib.setTwips(RtfPage.PAGE_HEIGHT, pagemaster.getPageHeight()); - + //Sets the document level property + attrib.set(RtfPage.ITAP, "0"); + Object widthRaw = attrib.getValue(RtfPage.PAGE_WIDTH); Object heightRaw = attrib.getValue(RtfPage.PAGE_HEIGHT); if ((widthRaw instanceof Integer) && (heightRaw instanceof Integer) @@ -84,7 +87,7 @@ final class PageAttributesConverter { bodyLeft = (Length) NumericOp.addition(pageLeft, bodyMargin.marginLeft); bodyRight = (Length) NumericOp.addition(pageRight, bodyMargin.marginRight); } - + attrib.setTwips(RtfPage.MARGIN_TOP, bodyTop); attrib.setTwips(RtfPage.MARGIN_BOTTOM, bodyBottom); attrib.setTwips(RtfPage.MARGIN_LEFT, bodyLeft); @@ -102,9 +105,9 @@ final class PageAttributesConverter { if (after != null) { afterBottom = (Length) NumericOp.addition(pageBottom, after.getExtent()); } - attrib.setTwips(RtfPage.FOOTERY, beforeTop); + attrib.setTwips(RtfPage.FOOTERY, afterBottom); } catch (Exception e) { - log.error("Exception in convertPageAttributes: " + log.error("Exception in convertPageAttributes: " + e.getMessage() + "- page attributes ignored"); attrib = new FOPRtfAttributes(); } diff --git a/src/java/org/apache/fop/render/rtf/RTFHandler.java b/src/java/org/apache/fop/render/rtf/RTFHandler.java index 568fe75aa..dd7a9bb3f 100644 --- a/src/java/org/apache/fop/render/rtf/RTFHandler.java +++ b/src/java/org/apache/fop/render/rtf/RTFHandler.java @@ -50,7 +50,6 @@ import org.apache.xmlgraphics.image.loader.util.ImageUtil; import org.apache.fop.apps.FOPException; import org.apache.fop.apps.FOUserAgent; import org.apache.fop.datatypes.LengthBase; -import org.apache.fop.datatypes.SimplePercentBaseContext; import org.apache.fop.fo.Constants; import org.apache.fop.fo.FOEventHandler; import org.apache.fop.fo.FONode; @@ -72,6 +71,7 @@ import org.apache.fop.fo.flow.ListItem; import org.apache.fop.fo.flow.ListItemBody; import org.apache.fop.fo.flow.ListItemLabel; import org.apache.fop.fo.flow.PageNumber; +import org.apache.fop.fo.flow.PageNumberCitation; import org.apache.fop.fo.flow.table.Table; import org.apache.fop.fo.flow.table.TableBody; import org.apache.fop.fo.flow.table.TableCell; @@ -85,8 +85,9 @@ import org.apache.fop.fo.pagination.Region; import org.apache.fop.fo.pagination.SimplePageMaster; import org.apache.fop.fo.pagination.StaticContent; import org.apache.fop.fo.properties.CommonBorderPaddingBackground; -import org.apache.fop.fo.properties.FixedLength; +import org.apache.fop.fo.properties.EnumLength; import org.apache.fop.fonts.FontSetup; +import org.apache.fop.layoutmgr.table.ColumnSetup; import org.apache.fop.render.DefaultFontResolver; import org.apache.fop.render.rtf.rtflib.rtfdoc.IRtfAfterContainer; import org.apache.fop.render.rtf.rtflib.rtfdoc.IRtfBeforeContainer; @@ -105,6 +106,7 @@ import org.apache.fop.render.rtf.rtflib.rtfdoc.RtfFootnote; import org.apache.fop.render.rtf.rtflib.rtfdoc.RtfHyperLink; import org.apache.fop.render.rtf.rtflib.rtfdoc.RtfList; import org.apache.fop.render.rtf.rtflib.rtfdoc.RtfListItem; +import org.apache.fop.render.rtf.rtflib.rtfdoc.RtfPage; import org.apache.fop.render.rtf.rtflib.rtfdoc.RtfSection; import org.apache.fop.render.rtf.rtflib.rtfdoc.RtfTable; import org.apache.fop.render.rtf.rtflib.rtfdoc.RtfTableCell; @@ -112,6 +114,7 @@ import org.apache.fop.render.rtf.rtflib.rtfdoc.RtfTableRow; import org.apache.fop.render.rtf.rtflib.rtfdoc.RtfTextrun; import org.apache.fop.render.rtf.rtflib.rtfdoc.RtfListItem.RtfListItemLabel; import org.apache.fop.render.rtf.rtflib.tools.BuilderContext; +import org.apache.fop.render.rtf.rtflib.tools.PercentContext; import org.apache.fop.render.rtf.rtflib.tools.TableContext; /** @@ -145,6 +148,10 @@ public class RTFHandler extends FOEventHandler { private SimplePageMaster pagemaster; + private int nestedTableDepth = 1; + + private PercentContext percentManager = new PercentContext(); + /** * Creates a new RTF structure handler. * @param userAgent the FOUserAgent for this process @@ -158,9 +165,7 @@ public class RTFHandler extends FOEventHandler { FontSetup.setup(fontInfo, null, new DefaultFontResolver(userAgent)); } - /** - * {@inheritDoc} - */ + /** {@inheritDoc} */ public void startDocument() throws SAXException { // TODO sections should be created try { @@ -172,9 +177,7 @@ public class RTFHandler extends FOEventHandler { } } - /** - * {@inheritDoc} - */ + /** {@inheritDoc} */ public void endDocument() throws SAXException { try { rtfFile.flush(); @@ -184,9 +187,7 @@ public class RTFHandler extends FOEventHandler { } } - /** - * {@inheritDoc} - */ + /** {@inheritDoc} */ public void startPageSequence(PageSequence pageSeq) { try { //This is needed for region handling @@ -195,10 +196,10 @@ public class RTFHandler extends FOEventHandler { this.pagemaster = pageSeq.getRoot().getLayoutMasterSet().getSimplePageMaster(reference); if (this.pagemaster == null) { - log.warn("Only simple-page-masters are supported on page-sequences: " + log.warn("Only simple-page-masters are supported on page-sequences: " + reference); log.warn("Using default simple-page-master from page-sequence-master..."); - PageSequenceMaster master + PageSequenceMaster master = pageSeq.getRoot().getLayoutMasterSet().getPageSequenceMaster(reference); this.pagemaster = master.getNextSimplePageMaster( false, false, false, false, false); @@ -223,6 +224,14 @@ public class RTFHandler extends FOEventHandler { builderContext.pushContainer(sect); + //Calculate usable page width for this flow + int useAblePageWidth = pagemaster.getPageWidth().getValue() + - pagemaster.getCommonMarginBlock().marginLeft.getValue() + - pagemaster.getCommonMarginBlock().marginRight.getValue() + - sect.getRtfAttributes().getValueAsInteger(RtfPage.MARGIN_LEFT).intValue() + - sect.getRtfAttributes().getValueAsInteger(RtfPage.MARGIN_RIGHT).intValue(); + percentManager.setDimension(pageSeq, useAblePageWidth); + bHeaderSpecified = false; bFooterSpecified = false; } catch (IOException ioe) { @@ -235,9 +244,7 @@ public class RTFHandler extends FOEventHandler { } } - /** - * {@inheritDoc} - */ + /** {@inheritDoc} */ public void endPageSequence(PageSequence pageSeq) { if (bDefer) { //If endBlock was called while SAX parsing, and the passed FO is Block @@ -255,9 +262,7 @@ public class RTFHandler extends FOEventHandler { } } - /** - * {@inheritDoc} - */ + /** {@inheritDoc} */ public void startFlow(Flow fl) { if (bDefer) { return; @@ -294,7 +299,7 @@ public class RTFHandler extends FOEventHandler { contAfter.newAfter(attr); } handled = true; - } else if (regionBefore != null + } else if (regionBefore != null && fl.getFlowName().equals(regionBefore.getRegionName())) { bHeaderSpecified = true; bPrevHeaderSpecified = true; @@ -313,7 +318,7 @@ public class RTFHandler extends FOEventHandler { RtfBefore before = c.newBefore(beforeAttributes); builderContext.pushContainer(before); handled = true; - } else if (regionAfter != null + } else if (regionAfter != null && fl.getFlowName().equals(regionAfter.getRegionName())) { bFooterSpecified = true; bPrevFooterSpecified = true; @@ -346,9 +351,7 @@ public class RTFHandler extends FOEventHandler { } } - /** - * {@inheritDoc} - */ + /** {@inheritDoc} */ public void endFlow(Flow fl) { if (bDefer) { return; @@ -360,10 +363,10 @@ public class RTFHandler extends FOEventHandler { Region regionAfter = pagemaster.getRegion(Constants.FO_REGION_AFTER); if (fl.getFlowName().equals(regionBody.getRegionName())) { //just do nothing - } else if (regionBefore != null + } else if (regionBefore != null && fl.getFlowName().equals(regionBefore.getRegionName())) { builderContext.popContainer(); - } else if (regionAfter != null + } else if (regionAfter != null && fl.getFlowName().equals(regionAfter.getRegionName())) { builderContext.popContainer(); } @@ -373,9 +376,7 @@ public class RTFHandler extends FOEventHandler { } } - /** - * {@inheritDoc} - */ + /** {@inheritDoc} */ public void startBlock(Block bl) { if (bDefer) { return; @@ -405,10 +406,7 @@ public class RTFHandler extends FOEventHandler { } } - - /** - * {@inheritDoc} - */ + /** {@inheritDoc} */ public void endBlock(Block bl) { if (bDefer) { @@ -435,9 +433,7 @@ public class RTFHandler extends FOEventHandler { } } - /** - * {@inheritDoc} - */ + /** {@inheritDoc} */ public void startBlockContainer(BlockContainer blc) { if (bDefer) { return; @@ -466,9 +462,7 @@ public class RTFHandler extends FOEventHandler { } } - /** - * {@inheritDoc} - */ + /** {@inheritDoc} */ public void endBlockContainer(BlockContainer bl) { if (bDefer) { return; @@ -494,9 +488,7 @@ public class RTFHandler extends FOEventHandler { } } - /** - * {@inheritDoc} - */ + /** {@inheritDoc} */ public void startTable(Table tbl) { if (bDefer) { return; @@ -509,15 +501,17 @@ public class RTFHandler extends FOEventHandler { final IRtfTableContainer tc = (IRtfTableContainer)builderContext.getContainer( IRtfTableContainer.class, true, null); - + RtfAttributes atts = TableAttributesConverter.convertTableAttributes(tbl); - + RtfTable table = tc.newTable(atts, tableContext); - + table.setNestedTableDepth(nestedTableDepth); + nestedTableDepth++; + CommonBorderPaddingBackground border = tbl.getCommonBorderPaddingBackground(); RtfAttributes borderAttributes = new RtfAttributes(); - + BorderAttributesConverter.makeBorder(border, CommonBorderPaddingBackground.BEFORE, borderAttributes, ITableAttributes.CELL_BORDER_TOP); BorderAttributesConverter.makeBorder(border, CommonBorderPaddingBackground.AFTER, @@ -526,9 +520,9 @@ public class RTFHandler extends FOEventHandler { borderAttributes, ITableAttributes.CELL_BORDER_LEFT); BorderAttributesConverter.makeBorder(border, CommonBorderPaddingBackground.END, borderAttributes, ITableAttributes.CELL_BORDER_RIGHT); - + table.setBorderAttributes(borderAttributes); - + builderContext.pushContainer(table); } catch (Exception e) { log.error("startTable:" + e.getMessage()); @@ -538,53 +532,32 @@ public class RTFHandler extends FOEventHandler { builderContext.pushTableContext(tableContext); } - /** - * {@inheritDoc} - */ + /** {@inheritDoc} */ public void endTable(Table tbl) { if (bDefer) { return; } + nestedTableDepth--; builderContext.popTableContext(); builderContext.popContainer(); } - /** - * - * @param tc TableColumn that is starting; - */ - + /** {@inheritDoc} */ public void startColumn(TableColumn tc) { if (bDefer) { return; } try { - /** - * Pass a SimplePercentBaseContext to getValue in order to - * avoid a NullPointerException, which occurs when you use - * proportional-column-width function in column-width attribute. - * Of course the results won't be correct, but at least the - * rest of the document will be rendered. Usage of the - * TableLayoutManager is not welcome due to design reasons and - * it also does not provide the correct values. - * TODO: Make proportional-column-width working for rtf output - */ - SimplePercentBaseContext context - = new SimplePercentBaseContext(null, - LengthBase.TABLE_UNITS, - 100000); - - Integer iWidth - = new Integer(tc.getColumnWidth().getValue(context) / 1000); - - String strWidth = iWidth.toString() + FixedLength.POINT; - Float width = new Float( - FoUnitsConverter.getInstance().convertToTwips(strWidth)); + int iWidth = tc.getColumnWidth().getValue(percentManager); + percentManager.setDimension(tc, iWidth); + + //convert to twips + Float width = new Float(FoUnitsConverter.getInstance().convertMptToTwips(iWidth)); builderContext.getTableContext().setNextColumnWidth(width); builderContext.getTableContext().setNextColumnRowSpanning( - new Integer(0), null); + new Integer(0), null); builderContext.getTableContext().setNextFirstSpanningCol(false); } catch (Exception e) { log.error("startColumn: " + e.getMessage()); @@ -593,45 +566,30 @@ public class RTFHandler extends FOEventHandler { } - /** - * - * @param tc TableColumn that is ending; - */ - + /** {@inheritDoc} */ public void endColumn(TableColumn tc) { if (bDefer) { return; } } - /** - * {@inheritDoc} - */ + /** {@inheritDoc} */ public void startHeader(TableBody th) { } - /** - * {@inheritDoc} - */ + /** {@inheritDoc} */ public void endHeader(TableBody th) { } - /** - * {@inheritDoc} - */ + /** {@inheritDoc} */ public void startFooter(TableBody tf) { } - /** - * {@inheritDoc} - */ + /** {@inheritDoc} */ public void endFooter(TableBody tf) { } - /** - * - * @param inl Inline that is starting. - */ + /** {@inheritDoc} */ public void startInline(Inline inl) { if (bDefer) { return; @@ -660,10 +618,7 @@ public class RTFHandler extends FOEventHandler { } } - /** - * - * @param inl Inline that is ending. - */ + /** {@inheritDoc} */ public void endInline(Inline inl) { if (bDefer) { return; @@ -685,9 +640,7 @@ public class RTFHandler extends FOEventHandler { } } - /** - * {@inheritDoc} - */ + /** {@inheritDoc} */ public void startBody(TableBody tb) { if (bDefer) { return; @@ -704,9 +657,7 @@ public class RTFHandler extends FOEventHandler { } } - /** - * {@inheritDoc} - */ + /** {@inheritDoc} */ public void endBody(TableBody tb) { if (bDefer) { return; @@ -721,9 +672,7 @@ public class RTFHandler extends FOEventHandler { } } - /** - * {@inheritDoc} - */ + /** {@inheritDoc} */ public void startRow(TableRow tr) { if (bDefer) { return; @@ -751,14 +700,12 @@ public class RTFHandler extends FOEventHandler { } } - /** - * {@inheritDoc} - */ + /** {@inheritDoc} */ public void endRow(TableRow tr) { if (bDefer) { return; } - + try { TableContext tctx = builderContext.getTableContext(); final RtfTableRow row = (RtfTableRow)builderContext.getContainer(RtfTableRow.class, @@ -771,11 +718,11 @@ public class RTFHandler extends FOEventHandler { RtfTableCell vCell = row.newTableCellMergedVertically( (int)tctx.getColumnWidth(), tctx.getColumnRowSpanningAttrs()); - + if (!tctx.getFirstSpanningCol()) { vCell.setHMerge(RtfTableCell.MERGE_WITH_PREVIOUS); } - + tctx.selectNextColumn(); } } catch (Exception e) { @@ -788,9 +735,7 @@ public class RTFHandler extends FOEventHandler { builderContext.getTableContext().decreaseRowSpannings(); } - /** - * {@inheritDoc} - */ + /** {@inheritDoc} */ public void startCell(TableCell tc) { if (bDefer) { return; @@ -811,11 +756,11 @@ public class RTFHandler extends FOEventHandler { RtfTableCell vCell = row.newTableCellMergedVertically( (int)tctx.getColumnWidth(), tctx.getColumnRowSpanningAttrs()); - + if (!tctx.getFirstSpanningCol()) { vCell.setHMerge(RtfTableCell.MERGE_WITH_PREVIOUS); } - + tctx.selectNextColumn(); } @@ -825,14 +770,14 @@ public class RTFHandler extends FOEventHandler { // create an RtfTableCell in the current RtfTableRow RtfAttributes atts = TableAttributesConverter.convertCellAttributes(tc); RtfTableCell cell = row.newTableCell((int)width, atts); - + //process number-rows-spanned attribute if (numberRowsSpanned > 1) { // Start vertical merge cell.setVMerge(RtfTableCell.MERGE_START); // set the number of rows spanned - tctx.setCurrentColumnRowSpanning(new Integer(numberRowsSpanned), + tctx.setCurrentColumnRowSpanning(new Integer(numberRowsSpanned), cell.getRtfAttributes()); } else { tctx.setCurrentColumnRowSpanning( @@ -842,33 +787,36 @@ public class RTFHandler extends FOEventHandler { //process number-columns-spanned attribute if (numberColumnsSpanned > 0) { // Get the number of columns spanned - RtfTable table = row.getTable(); tctx.setCurrentFirstSpanningCol(true); - + // We widthdraw one cell because the first cell is already created // (it's the current cell) ! for (int i = 0; i < numberColumnsSpanned - 1; ++i) { tctx.selectNextColumn(); - + + //aggregate width for further elements + width += tctx.getColumnWidth(); tctx.setCurrentFirstSpanningCol(false); RtfTableCell hCell = row.newTableCellMergedHorizontally( 0, null); - + if (numberRowsSpanned > 1) { // Start vertical merge hCell.setVMerge(RtfTableCell.MERGE_START); // set the number of rows spanned tctx.setCurrentColumnRowSpanning( - new Integer(numberRowsSpanned), + new Integer(numberRowsSpanned), cell.getRtfAttributes()); } else { tctx.setCurrentColumnRowSpanning( - new Integer(numberRowsSpanned), null); + new Integer(numberRowsSpanned), cell.getRtfAttributes()); } } } - + //save width of the cell, convert from twips to mpt + percentManager.setDimension(tc, (int)width * 50); + builderContext.pushContainer(cell); } catch (Exception e) { log.error("startCell: " + e.getMessage()); @@ -876,9 +824,7 @@ public class RTFHandler extends FOEventHandler { } } - /** - * {@inheritDoc} - */ + /** {@inheritDoc} */ public void endCell(TableCell tc) { if (bDefer) { return; @@ -889,9 +835,7 @@ public class RTFHandler extends FOEventHandler { } // Lists - /** - * {@inheritDoc} - */ + /** {@inheritDoc} */ public void startList(ListBlock lb) { if (bDefer) { return; @@ -917,9 +861,7 @@ public class RTFHandler extends FOEventHandler { } } - /** - * {@inheritDoc} - */ + /** {@inheritDoc} */ public void endList(ListBlock lb) { if (bDefer) { return; @@ -928,19 +870,17 @@ public class RTFHandler extends FOEventHandler { builderContext.popContainer(); } - /** - * {@inheritDoc} - */ + /** {@inheritDoc} */ public void startListItem(ListItem li) { if (bDefer) { return; } - + // create an RtfListItem in the current RtfList try { RtfList list = (RtfList)builderContext.getContainer( RtfList.class, true, this); - + /** * If the current list already contains a list item, then close the * list and open a new one, so every single list item gets its own @@ -954,11 +894,11 @@ public class RTFHandler extends FOEventHandler { this.endList((ListBlock) li.getParent()); this.startList((ListBlock) li.getParent()); this.startListBody(); - + list = (RtfList)builderContext.getContainer( RtfList.class, true, this); - } - + } + builderContext.pushContainer(list.newListItem()); } catch (IOException ioe) { log.error("startList: " + ioe.getMessage()); @@ -969,9 +909,7 @@ public class RTFHandler extends FOEventHandler { } } - /** - * {@inheritDoc} - */ + /** {@inheritDoc} */ public void endListItem(ListItem li) { if (bDefer) { return; @@ -980,9 +918,7 @@ public class RTFHandler extends FOEventHandler { builderContext.popContainer(); } - /** - * {@inheritDoc} - */ + /** {@inheritDoc} */ public void startListLabel() { if (bDefer) { return; @@ -1003,9 +939,7 @@ public class RTFHandler extends FOEventHandler { } } - /** - * {@inheritDoc} - */ + /** {@inheritDoc} */ public void endListLabel() { if (bDefer) { return; @@ -1014,46 +948,32 @@ public class RTFHandler extends FOEventHandler { builderContext.popContainer(); } - /** - * {@inheritDoc} - */ + /** {@inheritDoc} */ public void startListBody() { } - /** - * {@inheritDoc} - */ + /** {@inheritDoc} */ public void endListBody() { } // Static Regions - /** - * {@inheritDoc} - */ + /** {@inheritDoc} */ public void startStatic() { } - /** - * {@inheritDoc} - */ + /** {@inheritDoc} */ public void endStatic() { } - /** - * {@inheritDoc} - */ + /** {@inheritDoc} */ public void startMarkup() { } - /** - * {@inheritDoc} - */ + /** {@inheritDoc} */ public void endMarkup() { } - /** - * {@inheritDoc} - */ + /** {@inheritDoc} */ public void startLink(BasicLink basicLink) { if (bDefer) { return; @@ -1085,9 +1005,7 @@ public class RTFHandler extends FOEventHandler { } } - /** - * {@inheritDoc} - */ + /** {@inheritDoc} */ public void endLink() { if (bDefer) { return; @@ -1096,9 +1014,7 @@ public class RTFHandler extends FOEventHandler { builderContext.popContainer(); } - /** - * {@inheritDoc} - */ + /** {@inheritDoc} */ public void image(ExternalGraphic eg) { if (bDefer) { return; @@ -1115,32 +1031,30 @@ public class RTFHandler extends FOEventHandler { log.error("Image could not be found: " + uri); return; } - + putGraphic(eg, info); } catch (Exception e) { log.error("Error while handling an external-graphic: " + e.getMessage(), e); } } - /** - * {@inheritDoc} - */ + /** {@inheritDoc} */ public void foreignObject(InstreamForeignObject ifo) { if (bDefer) { return; } - + try { - XMLObj child = (XMLObj) ifo.getChildXMLObj(); + XMLObj child = ifo.getChildXMLObj(); Document doc = child.getDOMDocument(); String ns = child.getNamespaceURI(); - + ImageInfo info = new ImageInfo(null, null); // Set the resolution to that of the FOUserAgent FOUserAgent ua = ifo.getUserAgent(); ImageSize size = new ImageSize(); size.setResolution(ua.getSourceResolution()); - + // Set the image size to the size of the svg. Point2D csize = new Point2D.Float(-1, -1); Point2D intrinsicDimensions = child.getDimension(csize); @@ -1151,13 +1065,13 @@ public class RTFHandler extends FOEventHandler { info.setSize(size); ImageXMLDOM image = new ImageXMLDOM(info, doc, ns); - + FOUserAgent userAgent = ifo.getUserAgent(); ImageManager manager = userAgent.getFactory().getImageManager(); Map hints = ImageUtil.getDefaultHints(ua.getImageSessionContext()); Image converted = manager.convertImage(image, FLAVORS, hints); putGraphic(ifo, converted); - + } catch (Exception e) { log.error("Error while handling an instream-foreign-object: " + e.getMessage(), e); } @@ -1166,14 +1080,14 @@ public class RTFHandler extends FOEventHandler { private static final ImageFlavor[] FLAVORS = new ImageFlavor[] { ImageFlavor.RAW_EMF, ImageFlavor.RAW_PNG, ImageFlavor.RAW_JPEG }; - + /** * Puts a graphic/image into the generated RTF file. * @param abstractGraphic the graphic (external-graphic or instream-foreign-object) * @param info the image info object * @throws IOException In case of an I/O error */ - private void putGraphic(AbstractGraphics abstractGraphic, ImageInfo info) + private void putGraphic(AbstractGraphics abstractGraphic, ImageInfo info) throws IOException { try { FOUserAgent userAgent = abstractGraphic.getUserAgent(); @@ -1187,17 +1101,17 @@ public class RTFHandler extends FOEventHandler { log.error("Error while loading/processing image: " + info.getOriginalURI(), ie); } } - + /** * Puts a graphic/image into the generated RTF file. * @param abstractGraphic the graphic (external-graphic or instream-foreign-object) * @param image the image * @throws IOException In case of an I/O error */ - private void putGraphic(AbstractGraphics abstractGraphic, Image image) + private void putGraphic(AbstractGraphics abstractGraphic, Image image) throws IOException { byte[] rawData = null; - + ImageInfo info = image.getInfo(); if (image instanceof ImageRawStream) { @@ -1221,7 +1135,7 @@ public class RTFHandler extends FOEventHandler { IRtfTextrunContainer.class, true, this); final RtfExternalGraphic rtfGraphic = c.getTextrun().newImage(); - + //set URL if (info.getOriginalURI() != null) { rtfGraphic.setURL(info.getOriginalURI()); @@ -1296,16 +1210,12 @@ public class RTFHandler extends FOEventHandler { } } } - - /** - * {@inheritDoc} - */ + + /** {@inheritDoc} */ public void pageRef() { } - /** - * {@inheritDoc} - */ + /** {@inheritDoc} */ public void startFootnote(Footnote footnote) { if (bDefer) { return; @@ -1332,9 +1242,7 @@ public class RTFHandler extends FOEventHandler { } } - /** - * {@inheritDoc} - */ + /** {@inheritDoc} */ public void endFootnote(Footnote footnote) { if (bDefer) { return; @@ -1343,9 +1251,7 @@ public class RTFHandler extends FOEventHandler { builderContext.popContainer(); } - /** - * {@inheritDoc} - */ + /** {@inheritDoc} */ public void startFootnoteBody(FootnoteBody body) { if (bDefer) { return; @@ -1368,9 +1274,7 @@ public class RTFHandler extends FOEventHandler { } } - /** - * {@inheritDoc} - */ + /** {@inheritDoc} */ public void endFootnoteBody(FootnoteBody body) { if (bDefer) { return; @@ -1393,9 +1297,7 @@ public class RTFHandler extends FOEventHandler { } } - /** - * {@inheritDoc} - */ + /** {@inheritDoc} */ public void leader(Leader l) { } @@ -1432,10 +1334,7 @@ public class RTFHandler extends FOEventHandler { } } - /** - * - * @param pagenum PageNumber that is starting. - */ + /** {@inheritDoc} */ public void startPageNumber(PageNumber pagenum) { if (bDefer) { return; @@ -1461,16 +1360,64 @@ public class RTFHandler extends FOEventHandler { } } - /** - * - * @param pagenum PageNumber that is ending. - */ + /** {@inheritDoc} */ public void endPageNumber(PageNumber pagenum) { if (bDefer) { return; } } + /** {@inheritDoc} */ + public void startPageNumberCitation(PageNumberCitation l) { + if (bDefer) { + return; + } + try { + + IRtfTextrunContainer container + = (IRtfTextrunContainer)builderContext.getContainer( + IRtfTextrunContainer.class, true, this); + RtfTextrun textrun = container.getTextrun(); + + textrun.addPageNumberCitation(l.getRefId()); + + } catch (Exception e) { + log.error("startPageNumberCitation: " + e.getMessage()); + throw new RuntimeException(e.getMessage()); + } + } + + private void prepareTable(Table tab) { + // Allows to receive the available width of the table + percentManager.setDimension(tab); + + // Table gets expanded by half of the border on each side inside Word + // When using wide borders the table gets cut off + int tabDiff = tab.getCommonBorderPaddingBackground().getBorderStartWidth(false) / 2 + + tab.getCommonBorderPaddingBackground().getBorderEndWidth(false); + + // check for "auto" value + if (!(tab.getInlineProgressionDimension().getMaximum(null).getLength() + instanceof EnumLength)) { + // value specified + percentManager.setDimension(tab, + tab.getInlineProgressionDimension().getMaximum(null) + .getLength().getValue(percentManager) + - tabDiff); + } else { + // set table width again without border width + percentManager.setDimension(tab, percentManager.getBaseLength( + LengthBase.CONTAINING_BLOCK_WIDTH, tab) - tabDiff); + } + + ColumnSetup columnSetup = new ColumnSetup(tab); + //int sumOfColumns = columnSetup.getSumOfColumnWidths(percentManager); + float tableWidth = percentManager.getBaseLength(LengthBase.CONTAINING_BLOCK_WIDTH, tab); + float tableUnit = columnSetup.computeTableUnit(percentManager, Math.round(tableWidth)); + percentManager.setTableUnit(tab, Math.round(tableUnit)); + + } + /** * Calls the appropriate event handler for the passed FObj. * @@ -1611,6 +1558,12 @@ public class RTFHandler extends FOEventHandler { } else { endCell( (TableCell) foNode); } + } else if (foNode instanceof PageNumberCitation) { + if (bStart) { + startPageNumberCitation((PageNumberCitation) foNode); + } else { + endPageNumberCitation((PageNumberCitation) foNode); + } } else { log.warn("Ignored deferred event for " + foNode); } @@ -1651,9 +1604,12 @@ public class RTFHandler extends FOEventHandler { //recurse all table-columns if (table.getColumns() != null) { - for (Iterator it = table.getColumns().iterator(); it.hasNext();) { - recurseFONode( (FONode) it.next() ); - } + //Calculation for column-widths which are not set + prepareTable(table); + + for (Iterator it = table.getColumns().iterator(); it.hasNext();) { + recurseFONode( (FONode) it.next() ); + } } else { //TODO Implement implicit column setup handling! log.warn("No table-columns found on table. RTF output requires that all" diff --git a/src/java/org/apache/fop/render/rtf/rtflib/rtfdoc/RtfAttributes.java b/src/java/org/apache/fop/render/rtf/rtflib/rtfdoc/RtfAttributes.java index 92d6a5655..5ec5e907e 100644 --- a/src/java/org/apache/fop/render/rtf/rtflib/rtfdoc/RtfAttributes.java +++ b/src/java/org/apache/fop/render/rtf/rtflib/rtfdoc/RtfAttributes.java @@ -5,9 +5,9 @@ * The ASF licenses this file to You under the Apache License, Version 2.0 * (the "License"); you may not use this file except in compliance with * the License. You may obtain a copy of the License at - * + * * http://www.apache.org/licenses/LICENSE-2.0 - * + * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. @@ -28,6 +28,7 @@ package org.apache.fop.render.rtf.rtflib.rtfdoc; import java.util.HashMap; import java.util.Iterator; + import org.xml.sax.Attributes; import org.xml.sax.helpers.AttributesImpl; @@ -163,6 +164,15 @@ implements java.lang.Cloneable { return values.get(name); } + /** + * Returns a value as an Integer. The value is simply cast to an Integer. + * @param name String containing attribute name + * @return the value of an attribute, null if not found + */ + public Integer getValueAsInteger(String name) { + return (Integer)values.get(name); + } + /** * @param name String containing attribute name * @return true if given attribute is set @@ -215,17 +225,17 @@ implements java.lang.Cloneable { xslAttributes = new org.xml.sax.helpers.AttributesImpl(pAttribs); } } - + /** * Add integer value addValue to attribute with name name. - * If there is no such setted attribute, then value of this attribure is equal to + * If there is no such setted attribute, then value of this attribure is equal to * addValue. * @param addValue the increment of value * @param name the name of attribute */ public void addIntegerValue(int addValue, String name) { Integer value = (Integer) getValue(name); - int v = (value != null) ? value.intValue() : 0; + int v = (value != null) ? value.intValue() : 0; set(name, v + addValue); } } diff --git a/src/java/org/apache/fop/render/rtf/rtflib/rtfdoc/RtfPage.java b/src/java/org/apache/fop/render/rtf/rtflib/rtfdoc/RtfPage.java index bd2e9e62d..3662fb278 100644 --- a/src/java/org/apache/fop/render/rtf/rtflib/rtfdoc/RtfPage.java +++ b/src/java/org/apache/fop/render/rtf/rtflib/rtfdoc/RtfPage.java @@ -60,11 +60,13 @@ extends RtfContainer { public static final String HEADERY = "headery"; /** constant for footer position */ public static final String FOOTERY = "footery"; - + /** constant for itap level */ + public static final String ITAP = "itap"; + /** String array of RtfPage attributes */ public static final String[] PAGE_ATTR = new String[]{ PAGE_WIDTH, PAGE_HEIGHT, LANDSCAPE, MARGIN_TOP, MARGIN_BOTTOM, - MARGIN_LEFT, MARGIN_RIGHT, HEADERY, FOOTERY + MARGIN_LEFT, MARGIN_RIGHT, HEADERY, FOOTERY, ITAP }; /** RtfPage creates new page attributes with the parent container, the writer diff --git a/src/java/org/apache/fop/render/rtf/rtflib/rtfdoc/RtfPageNumberCitation.java b/src/java/org/apache/fop/render/rtf/rtflib/rtfdoc/RtfPageNumberCitation.java index c7f455c70..44c03c316 100644 --- a/src/java/org/apache/fop/render/rtf/rtflib/rtfdoc/RtfPageNumberCitation.java +++ b/src/java/org/apache/fop/render/rtf/rtflib/rtfdoc/RtfPageNumberCitation.java @@ -5,9 +5,9 @@ * The ASF licenses this file to You under the Apache License, Version 2.0 * (the "License"); you may not use this file except in compliance with * the License. You may obtain a copy of the License at - * + * * http://www.apache.org/licenses/LICENSE-2.0 - * + * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. @@ -26,8 +26,8 @@ package org.apache.fop.render.rtf.rtflib.rtfdoc; * the FOP project. */ -import java.io.Writer; import java.io.IOException; +import java.io.Writer; /** * @author Christopher Scott, scottc@westinghouse.com @@ -50,9 +50,9 @@ public class RtfPageNumberCitation extends RtfContainer { private String id = null; /** Create an RTF page number citation as a child of given container with default attributes */ - RtfPageNumberCitation (IRtfPageNumberCitationContainer parent, Writer w, String id) + RtfPageNumberCitation (RtfContainer parent, Writer w, String id) throws IOException { - super((RtfContainer)parent, w); + super(parent, w); this.id = id; } @@ -78,8 +78,8 @@ public class RtfPageNumberCitation extends RtfContainer { // Build page reference field String pageRef = RTF_FIELD_PAGEREF_MODEL; final int insertionIndex = pageRef.indexOf("}"); - pageRef = pageRef.substring(0, insertionIndex) - + "\"" + id + pageRef = pageRef.substring(0, insertionIndex) + + "\"" + id + "\"" + " " + pageRef.substring(insertionIndex, pageRef.length()); id = null; @@ -92,7 +92,7 @@ public class RtfPageNumberCitation extends RtfContainer { writeStarControlWord(pageRef); writeGroupMark(false); writeGroupMark(true); - writeControlWord(RTF_FIELD_RESULT); + writeControlWord(RTF_FIELD_RESULT + '#'); //To see where the page-number would be writeGroupMark(false); writeGroupMark(false); } diff --git a/src/java/org/apache/fop/render/rtf/rtflib/rtfdoc/RtfTable.java b/src/java/org/apache/fop/render/rtf/rtflib/rtfdoc/RtfTable.java index b8bb4b032..3747103d1 100644 --- a/src/java/org/apache/fop/render/rtf/rtflib/rtfdoc/RtfTable.java +++ b/src/java/org/apache/fop/render/rtf/rtflib/rtfdoc/RtfTable.java @@ -5,9 +5,9 @@ * The ASF licenses this file to You under the Apache License, Version 2.0 * (the "License"); you may not use this file except in compliance with * the License. You may obtain a copy of the License at - * + * * http://www.apache.org/licenses/LICENSE-2.0 - * + * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. @@ -26,8 +26,8 @@ package org.apache.fop.render.rtf.rtflib.rtfdoc; * the FOP project. */ -import java.io.Writer; import java.io.IOException; +import java.io.Writer; /** Container for RtfRow elements * @author Bertrand Delacretaz bdelacretaz@codeconsult.ch @@ -43,6 +43,9 @@ public class RtfTable extends RtfContainer { * number-columns-spanned attribute */ private ITableColumnsInfo tableContext; + /** Shows the table depth necessary for nested tables */ + private int nestedTableDepth = 0; + /** Create an RTF element as a child of given container */ RtfTable(IRtfTableContainer parent, Writer w, ITableColumnsInfo tc) throws IOException { @@ -110,16 +113,16 @@ public class RtfTable extends RtfContainer { writeControlWordNS("pard"); } - writeGroupMark(true); + writeGroupMark(true); } - + /** * Overridden to write RTF suffix code, what comes after our children * @throws IOException for I/O problems */ protected void writeRtfSuffix() throws IOException { writeGroupMark(false); - + if (isNestedTable()) { getRow().writeRowAndCellsDefintions(); } @@ -154,7 +157,7 @@ public class RtfTable extends RtfContainer { } /** - * + * * @return RtfAttributes of Header */ public RtfAttributes getHeaderAttribs() { @@ -173,7 +176,7 @@ public class RtfTable extends RtfContainer { return super.getRtfAttributes(); } - + /** @return true if the the table is a nested table */ public boolean isNestedTable() { if (isNestedTable == null) { @@ -194,9 +197,9 @@ public class RtfTable extends RtfContainer { return false; } - + /** - * + * * @return Parent row table (for nested tables only) */ public RtfTableRow getRow() { @@ -209,7 +212,23 @@ public class RtfTable extends RtfContainer { e = e.parent; } - return null; + return null; + } + + /** + * Sets the nested table depth. + * @param nestedTableDepth the nested table depth + */ + public void setNestedTableDepth(int nestedTableDepth) { + this.nestedTableDepth = nestedTableDepth; + } + + /** + * Returns the nested table depth. + * @return the nested table depth + */ + public int getNestedTableDepth() { + return this.nestedTableDepth; } /** @@ -219,7 +238,7 @@ public class RtfTable extends RtfContainer { public void setBorderAttributes(RtfAttributes attributes) { borderAttributes = attributes; } - + /** * Returns the RtfAttributes for the borders of the table. * @return Border attributes of the table. diff --git a/src/java/org/apache/fop/render/rtf/rtflib/rtfdoc/RtfTableRow.java b/src/java/org/apache/fop/render/rtf/rtflib/rtfdoc/RtfTableRow.java index 2182f94ec..f5e5978ec 100644 --- a/src/java/org/apache/fop/render/rtf/rtflib/rtfdoc/RtfTableRow.java +++ b/src/java/org/apache/fop/render/rtf/rtflib/rtfdoc/RtfTableRow.java @@ -5,9 +5,9 @@ * The ASF licenses this file to You under the Apache License, Version 2.0 * (the "License"); you may not use this file except in compliance with * the License. You may obtain a copy of the License at - * + * * http://www.apache.org/licenses/LICENSE-2.0 - * + * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. @@ -133,11 +133,11 @@ public class RtfTableRow extends RtfContainer implements ITableAttributes { * @throws IOException for I/O problems */ protected void writeRtfContent() throws IOException { - if (getTable().isNestedTable()) { //nested table writeControlWord("intbl"); - writeControlWord("itap2"); + //itap is the depth (level) of the current nested table + writeControlWord("itap" + getTable().getNestedTableDepth()); } else { //normal (not nested) table writeRowAndCellsDefintions(); @@ -145,15 +145,15 @@ public class RtfTableRow extends RtfContainer implements ITableAttributes { // now children can write themselves, we have the correct RTF prefix code super.writeRtfContent(); } - + /** - * + * * @throws IOException In case of a IO-problem */ public void writeRowAndCellsDefintions() throws IOException { // render the row and cells definitions writeControlWord("trowd"); - + if (!getTable().isNestedTable()) { writeControlWord("itap0"); } @@ -181,24 +181,24 @@ public class RtfTableRow extends RtfContainer implements ITableAttributes { // write X positions of our cells int xPos = 0; - + final Object leftIndent = attrib.getValue(ITableAttributes.ATTR_ROW_LEFT_INDENT); if (leftIndent != null) { xPos = ((Integer)leftIndent).intValue(); } - + RtfAttributes tableBorderAttributes = getTable().getBorderAttributes(); - + int index = 0; for (Iterator it = getChildren().iterator(); it.hasNext();) { final RtfElement e = (RtfElement)it.next(); if (e instanceof RtfTableCell) { - + RtfTableCell rtfcell = (RtfTableCell)e; - + // Adjust the cell's display attributes so the table's/row's borders // are drawn properly. - + if (tableBorderAttributes != null) { // get border attributes from table if (index == 0) { @@ -233,7 +233,7 @@ public class RtfTableRow extends RtfContainer implements ITableAttributes { } } } - + // get border attributes from row if (index == 0) { if (!rtfcell.getRtfAttributes().isSet(ITableAttributes.CELL_BORDER_LEFT)) { @@ -268,7 +268,7 @@ public class RtfTableRow extends RtfContainer implements ITableAttributes { } index++; // Added by Boris POUDEROUS on 2002/07/02 } - + newLine(); } @@ -366,9 +366,9 @@ public class RtfTableRow extends RtfContainer implements ITableAttributes { public boolean isHighestCell(int cellId) { return (highestCell == cellId) ? true : false; } - + /** - * + * * @return Parent table of the row. */ public RtfTable getTable() { @@ -381,6 +381,6 @@ public class RtfTableRow extends RtfContainer implements ITableAttributes { e = e.parent; } - return null; + return null; } } diff --git a/src/java/org/apache/fop/render/rtf/rtflib/rtfdoc/RtfTextrun.java b/src/java/org/apache/fop/render/rtf/rtflib/rtfdoc/RtfTextrun.java index 05a97ffd4..b0db4576b 100644 --- a/src/java/org/apache/fop/render/rtf/rtflib/rtfdoc/RtfTextrun.java +++ b/src/java/org/apache/fop/render/rtf/rtflib/rtfdoc/RtfTextrun.java @@ -5,9 +5,9 @@ * The ASF licenses this file to You under the Apache License, Version 2.0 * (the "License"); you may not use this file except in compliance with * the License. You may obtain a copy of the License at - * + * * http://www.apache.org/licenses/LICENSE-2.0 - * + * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. @@ -22,40 +22,37 @@ package org.apache.fop.render.rtf.rtflib.rtfdoc; // Java import java.io.IOException; import java.io.Writer; -import java.util.List; import java.util.Iterator; +import java.util.List; import java.util.ListIterator; -// FOP -import org.apache.fop.render.rtf.rtflib.rtfdoc.RtfExternalGraphic; - -/** - * Class which contains a linear text run. It has methods to add attributes, +/** + * 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 { private boolean bSuppressLastPar = false; private RtfListItem rtfListItem; - + /** Manager for handling space-* property. */ private RtfSpaceManager rtfSpaceManager = new RtfSpaceManager(); - + /** 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 @@ -65,22 +62,22 @@ public class RtfTextrun extends RtfContainer { 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 @@ -92,19 +89,19 @@ public class RtfTextrun extends RtfContainer { /** 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 @@ -113,16 +110,16 @@ public class RtfTextrun extends RtfContainer { 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); } - - + + /** * Adds instance of OpenGroupMark as a child with attributes. - * + * * @param attrs attributes to add * @throws IOException for I/O problems */ @@ -132,17 +129,17 @@ public class RtfTextrun extends RtfContainer { /** * Adds instance of CloseGroupMark as a child. - * + * * @throws IOException for I/O problems */ private void addCloseGroupMark() throws IOException { RtfCloseGroupMark r = new RtfCloseGroupMark(this, writer); } - + /** - * Pushes block attributes, notifies all opened blocks about pushing block + * Pushes block attributes, notifies all opened blocks about pushing block * attributes, adds OpenGroupMark as a child. - * + * * @param attrs the block attributes to push * @throws IOException for I/O problems */ @@ -151,11 +148,11 @@ public class RtfTextrun extends RtfContainer { RtfSpaceSplitter splitter = rtfSpaceManager.pushRtfSpaceSplitter(attrs); addOpenGroupMark(splitter.getCommonAttributes()); } - + /** - * Pops block attributes, notifies all opened blocks about pushing block + * Pops block attributes, notifies all opened blocks about pushing block * attributes, adds CloseGroupMark as a child. - * + * * @throws IOException for I/O problems */ public void popBlockAttributes() throws IOException { @@ -166,7 +163,7 @@ public class RtfTextrun extends RtfContainer { /** * Pushes inline attributes. - * + * * @param attrs the inline attributes to push * @throws IOException for I/O problems */ @@ -175,19 +172,28 @@ public class RtfTextrun extends RtfContainer { addOpenGroupMark(attrs); } + /** + * Inserts a page number citation. + * @param refId the identifier being referenced + * @throws IOException for I/O problems + */ + public void addPageNumberCitation(String refId) throws IOException { + RtfPageNumberCitation r = new RtfPageNumberCitation(this, writer, refId); + } + /** * Pop inline attributes. - * + * * @throws IOException for I/O problems */ public void popInlineAttributes() throws IOException { rtfSpaceManager.popInlineAttributes(); addCloseGroupMark(); } - + /** * Add string to children list. - * + * * @param s string to add * @throws IOException for I/O problems */ @@ -202,20 +208,20 @@ public class RtfTextrun extends RtfContainer { RtfString r = new RtfString(this, writer, s); rtfSpaceManager.popRtfSpaceSplitter(); } - + /** * Inserts a footnote. - * + * * @return inserted footnote * @throws IOException for I/O problems */ public RtfFootnote addFootnote() throws IOException { return new RtfFootnote(this, writer); } - + /** * Inserts paragraph break before all close group marks. - * + * * @throws IOException for I/O problems */ public void addParagraphBreak() throws IOException { @@ -241,7 +247,7 @@ public class RtfTextrun extends RtfContainer { } } } - + /** * Inserts a page number. * @param attr Attributes for the page number to insert. @@ -250,7 +256,7 @@ public class RtfTextrun extends RtfContainer { public void addPageNumber(RtfAttributes attr) throws IOException { RtfPageNumber r = new RtfPageNumber(this, writer, attr); } - + /** * Inserts a hyperlink. * @param attr Attributes for the hyperlink to insert. @@ -260,7 +266,7 @@ public class RtfTextrun extends RtfContainer { public RtfHyperLink addHyperlink(RtfAttributes attr) throws IOException { return new RtfHyperLink(this, writer, attr); } - + /** * Inserts a bookmark. * @param id Id for the inserted bookmark @@ -294,7 +300,7 @@ public class RtfTextrun extends RtfContainer { throws IOException { List list = container.getChildren(); - + if (list.size() == 0) { //add a new RtfTextrun RtfTextrun textrun = new RtfTextrun(container, writer, attrs); @@ -302,7 +308,7 @@ public class RtfTextrun extends RtfContainer { return textrun; } - + Object obj = list.get(list.size() - 1); if (obj instanceof RtfTextrun) { @@ -313,18 +319,18 @@ public class RtfTextrun extends RtfContainer { //add a new RtfTextrun as the last child RtfTextrun textrun = new RtfTextrun(container, writer, attrs); list.add(textrun); - + return textrun; } - + /** * specify, if the last paragraph control word (\par) should be suppressed. * @param bSuppress true, if the last \par should be suppressed - */ + */ public void setSuppressLastPar(boolean bSuppress) { bSuppressLastPar = bSuppress; } - + /** * write RTF code of all our children * @throws IOException for I/O problems @@ -336,7 +342,7 @@ public class RtfTextrun extends RtfContainer { * 2. To write the children * Maybe this can be done more efficient. */ - + boolean bHasTableCellParent = this.getParentOfClass(RtfTableCell.class) != null; RtfAttributes attrBlockLevel = new RtfAttributes(); @@ -349,7 +355,7 @@ public class RtfTextrun extends RtfContainer { break; } } - + //get last RtfParagraphBreak, which is not followed by any visible child RtfParagraphBreak lastParagraphBreak = null; if (bLast) { @@ -366,10 +372,10 @@ public class RtfTextrun extends RtfContainer { } } } - + //may contain for example \intbl writeAttributes(attrib, null); - + if (rtfListItem != null) { rtfListItem.getRtfListStyle().writeParagraphPrefix(this); } @@ -384,8 +390,8 @@ public class RtfTextrun extends RtfContainer { if (bHasTableCellParent) { attrBlockLevel.set(e.getRtfAttributes()); } - - + + /** * -Write RtfParagraphBreak only, if the previous visible child * was't also a RtfParagraphBreak. @@ -396,21 +402,21 @@ public class RtfTextrun extends RtfContainer { */ boolean bHide = false; bHide = bRtfParagraphBreak; - bHide = bHide - && (bPrevPar - || bFirst - || (bSuppressLastPar && bLast && lastParagraphBreak != null + bHide = bHide + && (bPrevPar + || bFirst + || (bSuppressLastPar && bLast && lastParagraphBreak != null && e == lastParagraphBreak)); - + if (!bHide) { newLine(); - e.writeRtf(); - + e.writeRtf(); + if (rtfListItem != null && e instanceof RtfParagraphBreak) { rtfListItem.getRtfListStyle().writeParagraphPrefix(this); } } - + if (e instanceof RtfParagraphBreak) { bPrevPar = true; } else if (e instanceof RtfCloseGroupMark) { @@ -422,26 +428,26 @@ public class RtfTextrun extends RtfContainer { bFirst = bFirst && e.isEmpty(); } } //for (Iterator it = ...) - + // if (bHasTableCellParent) { writeAttributes(attrBlockLevel, null); } - + } - + /** * Set the parent list-item of the textrun. - * + * * @param listItem parent list-item of the textrun */ public void setRtfListItem(RtfListItem listItem) { rtfListItem = listItem; } - + /** - * Gets the parent list-item of the textrun. - * + * Gets the parent list-item of the textrun. + * * @return parent list-item of the textrun */ public RtfListItem getRtfListItem() { diff --git a/src/java/org/apache/fop/render/rtf/rtflib/tools/PercentContext.java b/src/java/org/apache/fop/render/rtf/rtflib/tools/PercentContext.java new file mode 100644 index 000000000..732ecf99a --- /dev/null +++ b/src/java/org/apache/fop/render/rtf/rtflib/tools/PercentContext.java @@ -0,0 +1,157 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The ASF licenses this file to You under the Apache License, Version 2.0 + * (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +/* $Id$ */ + +package org.apache.fop.render.rtf.rtflib.tools; + +import java.util.Map; + +import org.apache.commons.logging.Log; +import org.apache.commons.logging.LogFactory; + +import org.apache.fop.datatypes.LengthBase; +import org.apache.fop.datatypes.PercentBaseContext; +import org.apache.fop.fo.FONode; +import org.apache.fop.fo.FObj; +import org.apache.fop.fo.flow.table.Table; +import org.apache.fop.fo.pagination.PageSequence; + +/** + * PercentBaseContext implementation to track base widths for percentage calculations. + */ +public class PercentContext implements PercentBaseContext { + private static Log log = LogFactory.getLog(PercentContext.class); + + private static final String BLOCKCONTAINER = "fo:block-container"; + private static final String INLINECONTAINER = "fo:inline-container"; + private static final String TABLE = "fo:table"; + private static final String TABLECOLUMN = "fo:table-column"; + private static final String PAGESEQUENCE = "fo:page-sequence"; + private static final String EXTERNALGRAPHIC = "fo:external-graphic"; + + /** String array of Elements having a width property */ + public static final String[] WIDTH_OBJECTS = new String[] { + BLOCKCONTAINER, INLINECONTAINER, + TABLE, TABLECOLUMN, PAGESEQUENCE, EXTERNALGRAPHIC}; + + /** Map containing the FObj and its width */ + private Map lengthMap = new java.util.HashMap(); + + /** Map containing the Tables and their table units */ + private Map tableUnitMap = new java.util.HashMap(); + + /** Variable to check if a base width is set */ + private boolean baseWidthSet = false; + + /** + * Returns the available width for a specific FObj + * + * @param lengthBase + * lengthBase not used + * @param fobj + * the FObj + * @return Available Width + */ + public int getBaseLength(int lengthBase, FObj fobj) { + if (fobj == null) { + return 0; + } + switch (lengthBase) { + case LengthBase.CONTAINING_BLOCK_WIDTH: + case LengthBase.PARENT_AREA_WIDTH: + case LengthBase.CONTAINING_REFAREA_WIDTH: + Object width = lengthMap.get(fobj); + if (width != null) { + return Integer.parseInt(width.toString()); + } else { + return -1; + } + case LengthBase.TABLE_UNITS: + Object unit = tableUnitMap.get(fobj); + /* + if (unit == null && !(fobj instanceof Table)) { + FONode node = fobj; + do { + node = node.getParent(); + } while (!(node instanceof FObj) || node != null); + return getBaseLength(lengthBase, (FObj)node); + } + */ + return (unit != null) ? ((Integer)unit).intValue() : 0; + default: + log.error(new Exception("Unsupported base type for LengthBase:" + lengthBase)); + return 0; + } + } + + /** + * Elements having a width property can call this function if their width is + * calculated in RTFHandler + * + * @param fobj the FObj + * @param width width of the FObj (in millipoints) + */ + public void setDimension(FObj fobj, int width) { + // TODO ACCEPT only objects above for setting a width + if (fobj instanceof PageSequence) { + baseWidthSet = true; + } + // width in mpt + lengthMap.put(fobj, new Integer(width)); + } + + /** + * Records the calculated table unit for a given table. + * @param table the table for which the table unit is set + * @param tableUnit the table unit value (in millipoints) + */ + public void setTableUnit(Table table, int tableUnit) { + tableUnitMap.put(table, new Integer(tableUnit)); + } + + /** + * Searches for the parent object of fobj. + */ + private Integer findParent(FONode fobj) { + if (fobj.getRoot() != fobj) { + if (lengthMap.containsKey(fobj)) { + return new Integer(lengthMap.get(fobj).toString()); + } else { + return findParent(fobj.getParent()); + } + } else { + log.error("Base Value for element " + fobj.getName() + " not found"); + return new Integer(-1); + } + } + + /** + * Elements willing to use this context have to register themselves by + * calling this function. + * + * @param fobj the FObj + */ + public void setDimension(FObj fobj) { + if (baseWidthSet) { + Integer width = findParent(fobj.getParent()); + if (width.intValue() != -1) { + lengthMap.put(fobj, width); + } + } + } +} diff --git a/status.xml b/status.xml index 6c557c251..5367daf3f 100644 --- a/status.xml +++ b/status.xml @@ -60,6 +60,13 @@ --> + + Added support for page-number-citation for RTF output. + + + Fixed handling of proportional-column-width() and percentages for table column in RTF + output. + Fixed two bugs concerning resolution handling with SVG images and their conversion to bitmaps for RTF output.