jeremias    2005/02/21 13:52:14

  Modified:    src/java/org/apache/fop/layoutmgr/table
                        TableLayoutManager.java Column.java Body.java
                        Row.java Cell.java
               src/java/org/apache/fop/fo/flow TableBody.java
               src/java/org/apache/fop/layoutmgr LayoutManagerMapping.java
               src/java/org/apache/fop/fo/properties
                        CommonBorderPaddingBackground.java
  Added:       src/java/org/apache/fop/layoutmgr/table
                        CollapsingBorderModelEyeCatching.java
                        CollapsingBorderModel.java GridUnit.java
  Log:
  First real step towards collapsing table borders.
  border-collapse="collapse" rules implemented but not fully tested, yet.
  Collapsing of borders works only for start and end borders, yet, and there 
only for non-spanned cells.
  CellLM is now prepared to get the full list of grid unit it occupies 
(necessary for collapsed border painting).
  Row.CellInfo extracted and renamed to GridUnit.
  WIP...
  
  Revision  Changes    Path
  1.20      +20 -2     
xml-fop/src/java/org/apache/fop/layoutmgr/table/TableLayoutManager.java
  
  Index: TableLayoutManager.java
  ===================================================================
  RCS file: 
/home/cvs/xml-fop/src/java/org/apache/fop/layoutmgr/table/TableLayoutManager.java,v
  retrieving revision 1.19
  retrieving revision 1.20
  diff -u -r1.19 -r1.20
  --- TableLayoutManager.java   15 Feb 2005 19:30:51 -0000      1.19
  +++ TableLayoutManager.java   21 Feb 2005 21:52:14 -0000      1.20
  @@ -280,11 +280,29 @@
           //new property evaluation context so proportional-column-width() 
works
           //correctly.
           if (columns.size() == 0) {
  -            this.columns.add(new Column(getTable().getDefaultColumn()));
  +            Column col = new Column(getTable().getDefaultColumn());
  +            col.setParent(this);
  +            this.columns.add(col);
           }
       }
       
       /**
  +     * @param column the column to check
  +     * @return true if the column is the first column
  +     */
  +    public boolean isFirst(Column column) {
  +        return (this.columns.size() == 0 || this.columns.get(0) == column);
  +    }
  +    
  +    /**
  +     * @param column the column to check
  +     * @return true if the column is the last column
  +     */
  +    public boolean isLast(Column column) {
  +        return (this.columns.size() == 0 || this.columns.get(columns.size() 
- 1) == column);
  +    }
  +    
  +    /**
        * Get the break possibility and height of the table header or footer.
        *
        * @param lm the header or footer layout manager
  @@ -455,6 +473,6 @@
               reset(null);
           }
       }
  -    
  +
   }
   
  
  
  
  1.9       +30 -2     
xml-fop/src/java/org/apache/fop/layoutmgr/table/Column.java
  
  Index: Column.java
  ===================================================================
  RCS file: 
/home/cvs/xml-fop/src/java/org/apache/fop/layoutmgr/table/Column.java,v
  retrieving revision 1.8
  retrieving revision 1.9
  diff -u -r1.8 -r1.9
  --- Column.java       20 Oct 2004 13:19:25 -0000      1.8
  +++ Column.java       21 Feb 2005 21:52:14 -0000      1.9
  @@ -1,5 +1,5 @@
   /*
  - * Copyright 1999-2004 The Apache Software Foundation.
  + * Copyright 1999-2005 The Apache Software Foundation.
    * 
    * Licensed under the Apache License, Version 2.0 (the "License");
    * you may not use this file except in compliance with the License.
  @@ -24,6 +24,7 @@
   import org.apache.fop.layoutmgr.LayoutContext;
   import org.apache.fop.layoutmgr.PositionIterator;
   import org.apache.fop.layoutmgr.TraitSetter;
  +import org.apache.fop.fo.flow.TableCell;
   import org.apache.fop.fo.flow.TableColumn;
   import org.apache.fop.area.Area;
   import org.apache.fop.area.Block;
  @@ -35,17 +36,36 @@
    * column properties.
    */
   public class Column extends AbstractLayoutManager {
  +    
       private TableColumn fobj;
       
  +    private Length columnWidth;
   
       /**
        * Create a new column layout manager.
  +     * @param node the table-column FO
        */
       public Column(TableColumn node) {
            super(node);
            fobj = node;
  +         columnWidth = fobj.getColumnWidth();
       }
   
  +    /** @return the table-column FO */
  +    public TableColumn getFObj() {
  +        return this.fobj;
  +    }
  +    
  +    /** @return true if the column is the first column */
  +    public boolean isFirst() {
  +        return ((TableLayoutManager)getParent()).isFirst(this);
  +    }
  +    
  +    /** @return true if the column is the last column */
  +    public boolean isLast() {
  +        return ((TableLayoutManager)getParent()).isLast(this);
  +    }
  +    
       /**
        * Get the next break possibility.
        * Columns do not create or return any areas.
  @@ -81,12 +101,20 @@
       }
   
       /**
  +     * Overrides the default column-with coming from the FO.
  +     * @param width the new width to use
  +     */
  +    public void setWidth(Length width) {
  +        this.columnWidth = width;
  +    }
  +    
  +    /**
        * Get the width of this column.
        *
        * @return the width of the column
        */
       public Length getWidth() {
  -        return fobj.getColumnWidth();
  +        return columnWidth;
       }
   
       /**
  
  
  
  1.14      +5 -0      xml-fop/src/java/org/apache/fop/layoutmgr/table/Body.java
  
  Index: Body.java
  ===================================================================
  RCS file: 
/home/cvs/xml-fop/src/java/org/apache/fop/layoutmgr/table/Body.java,v
  retrieving revision 1.13
  retrieving revision 1.14
  diff -u -r1.13 -r1.14
  --- Body.java 9 Feb 2005 15:38:15 -0000       1.13
  +++ Body.java 21 Feb 2005 21:52:14 -0000      1.14
  @@ -61,6 +61,11 @@
           fobj = node;
       }
   
  +    /** @return the table-body|header|footer FO */
  +    public TableBody getFObj() {
  +        return this.fobj;
  +    }
  +    
       /**
        * Set the columns from the table.
        *
  
  
  
  1.23      +130 -88   xml-fop/src/java/org/apache/fop/layoutmgr/table/Row.java
  
  Index: Row.java
  ===================================================================
  RCS file: /home/cvs/xml-fop/src/java/org/apache/fop/layoutmgr/table/Row.java,v
  retrieving revision 1.22
  retrieving revision 1.23
  diff -u -r1.22 -r1.23
  --- Row.java  9 Feb 2005 11:51:30 -0000       1.22
  +++ Row.java  21 Feb 2005 21:52:14 -0000      1.23
  @@ -20,8 +20,10 @@
   
   import org.apache.fop.fo.FONode;
   import org.apache.fop.fo.flow.Table;
  +import org.apache.fop.fo.flow.TableBody;
   import org.apache.fop.fo.flow.TableCell;
   import org.apache.fop.fo.flow.TableRow;
  +import org.apache.fop.fo.properties.CommonBorderPaddingBackground;
   import org.apache.fop.fo.properties.LengthRangeProperty;
   import org.apache.fop.layoutmgr.BlockStackingLayoutManager;
   import org.apache.fop.layoutmgr.LayoutManager;
  @@ -52,16 +54,9 @@
    */
   public class Row extends BlockStackingLayoutManager {
       
  -    /** Used by CellInfo: Indicates start of cell. */
  -    public static final int CI_START_OF_CELL = 0;
  -    /** Used by CellInfo: Indicates part of a spanned cell in column 
direction. */
  -    public static final int CI_COL_SPAN      = 1;
  -    /** Used by CellInfo: Indicates part of a spanned cell in row direction. 
*/
  -    public static final int CI_ROW_SPAN      = 2;
  -    
       private TableRow fobj;
       
  -    private List cellList = null;
  +    private List gridUnits = null;
       private List columns = null;
       private int referenceIPD;
       private int rowHeight;
  @@ -85,6 +80,11 @@
           fobj = node;
       }
   
  +    /** @return the table-row FO */
  +    public TableRow getFObj() {
  +        return this.fobj;
  +    }
  +    
       /**
        * @return the table owning this row
        */
  @@ -105,8 +105,32 @@
           columns = cols;
       }
   
  -    private void setupCells() {
  -        cellList = new java.util.ArrayList();
  +    /** @return true if this is the layout manager for the first row in a 
body. */
  +    public boolean isFirstInBody() {
  +        return ((TableBody)getFObj().getParent()).isFirst(getFObj());
  +    }
  +    
  +    /** @return true if this is the layout manager for the last row in a 
body. */
  +    public boolean isLastInBody() {
  +        return ((TableBody)getFObj().getParent()).isLast(getFObj());
  +    }
  +    
  +    /**
  +     * Gets the Column at a given index.
  +     * @param index index of the column (index must be >= 1)
  +     * @return the requested Column
  +     */
  +    private Column getColumn(int index) {
  +        int size = columns.size();
  +        if (index > size - 1) {
  +            return (Column)columns.get(size - 1);
  +        } else {
  +            return (Column)columns.get(index - 1);
  +        }
  +    }
  +    
  +    private void prepareGridUnits() {
  +        gridUnits = new java.util.ArrayList();
           List availableCells = new java.util.ArrayList();
           // add cells to list
           while (childLMiter.hasNext()) {
  @@ -125,55 +149,108 @@
               if (cell.hasColumnNumber()) {
                   colnum = cell.getColumnNumber();
               }
  -            while (colnum > cellList.size()) {
  -                cellList.add(null);
  +            while (colnum > gridUnits.size()) {
  +                gridUnits.add(null);
               }
  -            if (cellList.get(colnum - 1) != null) {
  +            if (gridUnits.get(colnum - 1) != null) {
                   log.error("Overlapping cell at position " + colnum);
               }
               //Add cell info for primary slot
  -            cellList.set(colnum - 1, new CellInfo(cellLM));
  +            GridUnit info = new GridUnit(cellLM);
  +            info.row = this;
  +            gridUnits.set(colnum - 1, info);
  +            info.column = getColumn(colnum);
               
               //Add cell infos on spanned slots if any
               for (int j = 1; j < cell.getNumberColumnsSpanned(); j++) {
                   colnum++;
  -                if (colnum > cellList.size()) {
  -                    cellList.add(new CellInfo(CI_COL_SPAN));
  +                GridUnit infoSpan = new GridUnit(cellLM, j);
  +                infoSpan.row = this;
  +                infoSpan.column = getColumn(colnum);
  +                if (colnum > gridUnits.size()) {
  +                    gridUnits.add(infoSpan);
                   } else {
  -                    if (cellList.get(colnum - 1) != null) {
  +                    if (gridUnits.get(colnum - 1) != null) {
                           log.error("Overlapping cell at position " + colnum);
  +                        //TODO throw layout exception
                       }
  -                    cellList.set(colnum - 1, new CellInfo(CI_COL_SPAN));
  +                    gridUnits.set(colnum - 1, infoSpan);
                   }
               }
               colnum++;
           }
           
  -        //Post-processing the list (looking for gaps)
  -        int pos = 1;
  -        ListIterator ppIter = cellList.listIterator();
  -        while (ppIter.hasNext()) {
  -            CellInfo cellInfo = (CellInfo)ppIter.next();
  -            if (cellInfo == null) {
  -                //Add cell info on empty cell
  -                ppIter.set(new CellInfo(CI_START_OF_CELL));
  +        //Post-processing the list (looking for gaps and resolve start and 
end borders)
  +        postProcessGridUnits();
  +    }
  +
  +    private void postProcessGridUnits() {
  +        for (int pos = 1; pos <= gridUnits.size(); pos++) {
  +            GridUnit gu = (GridUnit)gridUnits.get(pos - 1);
  +            
  +            //Empty grid units
  +            if (gu == null) {
  +                //Add grid unit
  +                gu = new GridUnit(null);
  +                gu.row = this;
  +                gu.column = getColumn(pos);
  +                gridUnits.set(pos - 1, gu);
  +            }
  +        }
  +            
  +        //Border resolution now that the empty grid units are filled
  +        for (int pos = 1; pos <= gridUnits.size(); pos++) {
  +            GridUnit gu = (GridUnit)gridUnits.get(pos - 1);
  +         
  +            //Border resolution
  +            if (getTable().isSeparateBorderModel()) {
  +                gu.assignBorder(gu.layoutManager);
  +            } else {
  +                GridUnit start = null;
  +                int find = pos - 1;
  +                while (find >= 1) {
  +                    GridUnit candidate = (GridUnit)gridUnits.get(find - 1);
  +                    if (candidate.isLastGridUnitColSpan()) {
  +                        start = candidate;
  +                        break;
  +                    }
  +                    find--;
  +                }
  +                GridUnit end = null;
  +                find = pos + 1;
  +                while (find <= gridUnits.size()) {
  +                    GridUnit candidate = (GridUnit)gridUnits.get(find - 1);
  +                    if (candidate.isPrimaryGridUnit()) {
  +                        end = candidate;
  +                        break;
  +                    }
  +                }
  +                CommonBorderPaddingBackground borders = new 
CommonBorderPaddingBackground();
  +                GridUnit.resolveBorder(getTable(), borders, gu, 
  +                        (start != null ? start : null), 
  +                        CommonBorderPaddingBackground.START);
  +                GridUnit.resolveBorder(getTable(), borders, gu, 
  +                        (end != null ? end : null), 
  +                        CommonBorderPaddingBackground.END);
  +                gu.effBorders = borders;
  +                //Only start and end borders here, before and after during 
layout
  +                //TODO resolve before and after borders during layout
               }
  -            pos++;
           }
       }
  -
  +    
       /**
        * Get the cell info for a cell.
        *
        * @param pos the position of the cell (must be >= 1)
        * @return the cell info object
        */
  -    protected CellInfo getCellInfo(int pos) {
  -        if (cellList == null) {
  -            setupCells();
  +    protected GridUnit getCellInfo(int pos) {
  +        if (gridUnits == null) {
  +            prepareGridUnits();
           }
  -        if (pos <= cellList.size()) {
  -            return (CellInfo)cellList.get(pos - 1);
  +        if (pos <= gridUnits.size()) {
  +            return (GridUnit)gridUnits.get(pos - 1);
           } else {
               return null;
           }
  @@ -189,11 +266,10 @@
        */
       public BreakPoss getNextBreakPoss(LayoutContext context) {
           //LayoutManager curLM; // currently active LM
  -        CellInfo curCellInfo; //currently active cell info
  +        GridUnit curGridUnit; //currently active grid unit
   
           BreakPoss lastPos = null;
           List breakList = new java.util.ArrayList();
  -        List spannedColumns = new java.util.ArrayList();
   
           int min = 0;
           int opt = 0;
  @@ -205,9 +281,9 @@
           int startColumn = 1;
           boolean over = false;
   
  -        while ((curCellInfo = getCellInfo(startColumn)) != null) {
  -            Cell cellLM = curCellInfo.layoutManager;
  -            if (curCellInfo.isColSpan()) {
  +        while ((curGridUnit = getCellInfo(startColumn)) != null) {
  +            Cell cellLM = curGridUnit.layoutManager;
  +            if (curGridUnit.isColSpan()) {
                   //skip spanned slots
                   startColumn++;
                   continue;
  @@ -227,15 +303,17 @@
                                        stackSize));
   
               //Determine which columns this cell will occupy
  -            getColumnsForCell(cellLM, startColumn, spannedColumns);
  +            List spannedGridUnits = new java.util.ArrayList();
  +            getGridUnitsForCell(cellLM, startColumn, spannedGridUnits);
               int childRefIPD = 0;
  -            for (int i = 0; i < spannedColumns.size(); i++) {
  -                Column col = (Column)spannedColumns.get(i);
  +            for (int i = 0; i < spannedGridUnits.size(); i++) {
  +                Column col = ((GridUnit)spannedGridUnits.get(i)).column;
                   childRefIPD += col.getWidth().getValue();
               }
               childLC.setRefIPD(childRefIPD);
   
               if (cellLM != null) {
  +                cellLM.addGridUnitsFromRow(spannedGridUnits);
                   cellLM.setInRowIPDOffset(ipdOffset);
                   while (!cellLM.isFinished()) {
                       if ((bp = cellLM.getNextBreakPoss(childLC)) != null) {
  @@ -309,8 +387,8 @@
           boolean fin = true;
           startColumn = 1;
           //Check if any of the cell LMs haven't finished, yet
  -        while ((curCellInfo = getCellInfo(startColumn)) != null) {
  -            Cell cellLM = curCellInfo.layoutManager;
  +        while ((curGridUnit = getCellInfo(startColumn)) != null) {
  +            Cell cellLM = curGridUnit.layoutManager;
               if (cellLM == null) {
                   //skip empty cell
                   startColumn++;
  @@ -334,26 +412,12 @@
       }
   
       /**
  -     * Gets the Column at a given index.
  -     * @param index index of the column (index must be >= 1)
  -     * @return the requested Column
  -     */
  -    private Column getColumn(int index) {
  -        int size = columns.size();
  -        if (index > size - 1) {
  -            return (Column)columns.get(size - 1);
  -        } else {
  -            return (Column)columns.get(index - 1);
  -        }
  -    }
  -    
  -    /**
        * Determines the columns that are spanned by the given cell.
        * @param cellLM table-cell LM
        * @param startCell starting cell index (must be >= 1)
        * @param spannedColumns List to receive the applicable columns
        */
  -    private void getColumnsForCell(Cell cellLM, int startCell, List 
spannedColumns) {
  +    private void getGridUnitsForCell(Cell cellLM, int startCell, List 
spannedColumns) {
           int count;
           if (cellLM != null) {
               count = cellLM.getFObj().getNumberColumnsSpanned();
  @@ -362,7 +426,7 @@
           }
           spannedColumns.clear();
           for (int i = 0; i < count; i++) {
  -            spannedColumns.add(getColumn(startCell + i));
  +            spannedColumns.add(this.gridUnits.get(startCell + i - 1));
           }
       }
   
  @@ -376,13 +440,13 @@
        */
       protected void reset(Position pos) {
           //LayoutManager curLM; // currently active LM
  -        CellInfo curCellInfo;
  +        GridUnit curGridUnit;
           int cellIndex = 1;
   
           if (pos == null) {
  -            while ((curCellInfo = getCellInfo(cellIndex)) != null) {
  -                if (curCellInfo.layoutManager != null) {
  -                    curCellInfo.layoutManager.resetPosition(null);
  +            while ((curGridUnit = getCellInfo(cellIndex)) != null) {
  +                if (curGridUnit.layoutManager != null) {
  +                    curGridUnit.layoutManager.resetPosition(null);
                   }
                   cellIndex++;
               }
  @@ -390,10 +454,10 @@
               RowPosition rpos = (RowPosition)pos;
               List breaks = rpos.cellBreaks;
   
  -            while ((curCellInfo = getCellInfo(cellIndex)) != null) {
  -                if (curCellInfo.layoutManager != null) {
  +            while ((curGridUnit = getCellInfo(cellIndex)) != null) {
  +                if (curGridUnit.layoutManager != null) {
                       List childbreaks = (List)breaks.get(cellIndex);
  -                    curCellInfo.layoutManager.resetPosition(
  +                    curGridUnit.layoutManager.resetPosition(
                               (Position)childbreaks.get(childbreaks.size() - 
1));
                   }
                   cellIndex++;
  @@ -540,27 +604,5 @@
           }
       }
   
  -    private class CellInfo {
  -        
  -        /** layout manager for this cell, may be null */
  -        public Cell layoutManager;
  -        /** flags for this cell, on of Row.CI_* */
  -        public int flags = CI_START_OF_CELL;
  -        
  -        public CellInfo(Cell layoutManager) {
  -            this.layoutManager = layoutManager;
  -        }
  -        
  -        public CellInfo(int flags) {
  -            this.flags = flags;
  -        }
  -        
  -        /** @return true if the cell is part of a span in column direction */
  -        public boolean isColSpan() {
  -            return (flags & CI_COL_SPAN) != 0;
  -        }
  -
  -    }
  -    
   }
   
  
  
  
  1.23      +43 -5     xml-fop/src/java/org/apache/fop/layoutmgr/table/Cell.java
  
  Index: Cell.java
  ===================================================================
  RCS file: 
/home/cvs/xml-fop/src/java/org/apache/fop/layoutmgr/table/Cell.java,v
  retrieving revision 1.22
  retrieving revision 1.23
  diff -u -r1.22 -r1.23
  --- Cell.java 16 Feb 2005 10:15:45 -0000      1.22
  +++ Cell.java 21 Feb 2005 21:52:14 -0000      1.23
  @@ -21,6 +21,7 @@
   import org.apache.fop.fo.FONode;
   import org.apache.fop.fo.flow.Table;
   import org.apache.fop.fo.flow.TableCell;
  +import org.apache.fop.fo.properties.CommonBorderPaddingBackground;
   import org.apache.fop.fo.properties.LengthRangeProperty;
   import org.apache.fop.layoutmgr.BlockStackingLayoutManager;
   import org.apache.fop.layoutmgr.LayoutManager;
  @@ -59,9 +60,14 @@
       private int cellIPD;
       private int rowHeight;
       private int usedBPD;
  +    private int startBorderWidth;
  +    private int endBorderWidth;
       private int borderAndPaddingBPD;
       private boolean emptyCell = true;
   
  +    /** List of Lists containing GridUnit instances, one List per row. */
  +    private List rows = new java.util.ArrayList(); 
  +    
       /**
        * Create a new Cell layout manager.
        * @node table-cell FO for which to create the LM
  @@ -102,10 +108,34 @@
           return (Table)node;
       }
       
  +
  +    /**
  +     * Called by Row LM to register the grid units occupied by this cell for 
a row.
  +     * @param spannedGridUnits a List of GridUnits
  +     */
  +    public void addGridUnitsFromRow(List spannedGridUnits) {
  +        log.debug("Getting another row, " + spannedGridUnits.size() + " grid 
units");
  +        this.rows.add(spannedGridUnits);
  +        
  +    }
  +
       private int getIPIndents() {
           int iIndents = 0;
  -        iIndents += 
fobj.getCommonBorderPaddingBackground().getBorderStartWidth(false);
  -        iIndents += 
fobj.getCommonBorderPaddingBackground().getBorderEndWidth(false);
  +        startBorderWidth = 0;
  +        endBorderWidth = 0;
  +        for (int i = 0; i < rows.size(); i++) {
  +            List gridUnits = (List)rows.get(i);
  +            startBorderWidth = Math.max(startBorderWidth, 
  +                    ((GridUnit)gridUnits.get(0)).
  +                        effBorders.getBorderStartWidth(false));
  +            endBorderWidth = Math.max(endBorderWidth, 
  +                    ((GridUnit)gridUnits.get(gridUnits.size() - 1)).
  +                        effBorders.getBorderEndWidth(false));
  +        }
  +        //iIndents += 
fobj.getCommonBorderPaddingBackground().getBorderStartWidth(false);
  +        iIndents += startBorderWidth;
  +        //iIndents += 
fobj.getCommonBorderPaddingBackground().getBorderEndWidth(false);
  +        iIndents += endBorderWidth;
           if (!fobj.isSeparateBorderModel()) {
               iIndents /= 2;
           }
  @@ -277,8 +307,15 @@
               TraitSetter.addBackground(curBlockArea, 
fobj.getCommonBorderPaddingBackground());
               //TODO Set these booleans right
               boolean[] outer = new boolean[] {false, false, false, false};
  -            TraitSetter.addCollapsingBorders(curBlockArea, 
  -                    fobj.getCommonBorderPaddingBackground(), outer);
  +            if (rows.size() == 1 && ((List)rows.get(0)).size() == 1) {
  +                //Can set the borders directly if there's no span
  +                CommonBorderPaddingBackground effBorders =
  +                    ((GridUnit)((List)rows.get(0)).get(0)).effBorders;
  +                TraitSetter.addCollapsingBorders(curBlockArea, 
  +                        effBorders, outer);
  +            } else {
  +                log.warn("TODO Add collapsed border painting for spanned 
cells");
  +            }
           }
   
           //Handle display-align
  @@ -339,7 +376,7 @@
               curBlockArea.addTrait(Trait.IS_REFERENCE_AREA, Boolean.TRUE);
               curBlockArea.setPositioning(Block.ABSOLUTE);
               int indent = 0;
  -            indent += 
fobj.getCommonBorderPaddingBackground().getBorderStartWidth(false);
  +            indent += startBorderWidth;
               if (!fobj.isSeparateBorderModel()) {
                   indent /= 2;
               }
  @@ -390,5 +427,6 @@
               childBreaks.clear();
           }
       }
  +
   }
   
  
  
  
  1.1                  
xml-fop/src/java/org/apache/fop/layoutmgr/table/CollapsingBorderModelEyeCatching.java
  
  Index: CollapsingBorderModelEyeCatching.java
  ===================================================================
  /*
   * Copyright 2005 The Apache Software Foundation.
   *
   * Licensed 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: CollapsingBorderModelEyeCatching.java,v 1.1 2005/02/21 21:52:14 
jeremias Exp $ */
  
  package org.apache.fop.layoutmgr.table;
  
  import org.apache.fop.fo.Constants;
  import org.apache.fop.fo.properties.CommonBorderPaddingBackground;
  import org.apache.fop.fo.properties.CommonBorderPaddingBackground.BorderInfo;
  
  /**
   * Implements the normal "collapse" border model defined in 6.7.10 in XSL 1.0.
   * 
   * TODO Column groups are not yet checked in this algorithm!
   */
  public class CollapsingBorderModelEyeCatching extends CollapsingBorderModel {
  
      private static final int BEFORE = CommonBorderPaddingBackground.BEFORE;
      private static final int AFTER = CommonBorderPaddingBackground.AFTER;
      private static final int START = CommonBorderPaddingBackground.START;
      private static final int END = CommonBorderPaddingBackground.END;
      
      public BorderInfo determineWinner(GridUnit currentGridUnit, 
              GridUnit otherGridUnit, int side, int flags) {
          final boolean vertical = isVerticalRelation(side);
          final int otherSide = getOtherSide(side);
          
          //Get cells
          Cell currentCell = currentGridUnit.layoutManager;
          Cell otherCell = null;
          if (otherGridUnit != null) {
              otherCell = otherGridUnit.layoutManager;
          }
          
          //Get rows
          Row currentRow = currentGridUnit.row;
          Row otherRow = null;
          if (vertical && otherCell != null) {
              otherRow = otherGridUnit.row;
          }
          
          //get bodies
          Body currentBody = (Body)currentRow.getParent();
          Body otherBody = null;
          if (otherRow != null) {
              otherBody = (Body)otherRow.getParent();
          }
  
          //get columns
          Column currentColumn = (Column)currentGridUnit.column;
          Column otherColumn = null;
          if (otherGridUnit != null) {
              otherColumn = (Column)otherGridUnit.column;
          }
          
          //TODO get column groups
          
          //Get table
          TableLayoutManager table = 
(TableLayoutManager)currentBody.getParent();
          
          
//----------------------------------------------------------------------
          //We're creating two arrays containing the applicable BorderInfos for
          //each cell in question.
          //0 = cell, 1 = row, 2 = row group (body), 3 = column, 
          //4 = col group (spanned column, see 6.7.3), 5 = table
  
          BorderInfo[] current = new BorderInfo[6];
          BorderInfo[] other = new BorderInfo[6];
          //cell
          current[0] = currentGridUnit.getOriginalBorderInfoForCell(side);
          if (otherGridUnit != null) {
              other[0] = otherGridUnit.getOriginalBorderInfoForCell(otherSide);
          }
          if (side == BEFORE 
                  || side == AFTER
                  || (currentColumn.isFirst() && side == START)
                  || (currentColumn.isLast() && side == END)) {
              //row
              current[1] = 
currentRow.getFObj().getCommonBorderPaddingBackground().getBorderInfo(side);
          }
          if (otherRow != null) {
              //row
              other[1] = 
otherRow.getFObj().getCommonBorderPaddingBackground().getBorderInfo(otherSide);
          }
          if ((side == BEFORE && currentRow.isFirstInBody())
                  || (side == AFTER && currentRow.isLastInBody())
                  || (currentColumn.isFirst() && side == START)
                  || (currentColumn.isLast() && side == END)) {
              //row group (=body, table-header or table-footer)
              current[2] = 
currentBody.getFObj().getCommonBorderPaddingBackground().getBorderInfo(side);
          }
          if ((otherSide == BEFORE && otherRow.isFirstInBody())
                  || (otherSide == AFTER && otherRow.isLastInBody())) {
              //row group (=body, table-header or table-footer)
              other[2] = 
otherBody.getFObj().getCommonBorderPaddingBackground().getBorderInfo(otherSide);
          }
          if ((side == BEFORE && otherGridUnit == null)
                  || (side == AFTER && otherGridUnit == null)
                  || (side == START)
                  || (side == END)) {
              //column
              current[3] = 
currentColumn.getFObj().getCommonBorderPaddingBackground().getBorderInfo(side);
          }
          if (otherColumn != null) {
              //column
              other[3] = 
otherColumn.getFObj().getCommonBorderPaddingBackground().getBorderInfo(otherSide);
          }
          //TODO current[4] and other[4] for column groups
          if (otherGridUnit == null) {
              //table
              current[5] = 
table.getTable().getCommonBorderPaddingBackground().getBorderInfo(side);
          }
          //other[6] is always null, since it's always the same table
          
          BorderInfo resolved = null;
          
          // *** Rule 1 ***
          resolved = doRule1(current, other);
          if (resolved != null) {
              return resolved;
          }
          
          // *** Rule 2 ***
          if (!doRule2(current, other)) {
              return null; //paint no border
          }
          
          // *** Rule 3 ***
          resolved = doRule3(current, other);
          if (resolved != null) {
              return resolved;
          }
          
          // *** Rule 4 ***
          resolved = doRule4(current, other);
          if (resolved != null) {
              return resolved;
          }
          
          // *** Rule 5 ***
          resolved = doRule5(current, other);
          if (resolved != null) {
              return resolved;
          }
          
          return null; //no winner, no border
      }
  
      private BorderInfo doRule1(BorderInfo[] current, BorderInfo[] other) {
          for (int i = 0; i < current.length - 1; i++) {
              if ((current[i] != null) && (current[i].getStyle() == 
Constants.EN_HIDDEN)) {
                  return current[i];
              }
              if ((other[i] != null) && (other[i].getStyle() == 
Constants.EN_HIDDEN)) {
                  return other[i];
              }
          }
          return null;
      }
      
      private boolean doRule2(BorderInfo[] current, BorderInfo[] other) {
          boolean found = false;
          for (int i = 0; i < current.length - 1; i++) {
              if ((current[i] != null) && (current[i].getStyle() != 
Constants.EN_NONE)) {
                  found = true;
                  break;
              }
              if ((other[i] != null) && (other[i].getStyle() != 
Constants.EN_NONE)) {
                  found = true;
                  break;
              }
          }
          return found;
      }
  
      private BorderInfo doRule3(BorderInfo[] current, BorderInfo[] other) {
          int width = 0;
          //Find max border width
          for (int i = 0; i < current.length - 1; i++) {
              if ((current[i] != null) && (current[i].getRetainedWidth() > 
width)) {
                  width = current[i].getRetainedWidth();
              }
              if ((other[i] != null) && (other[i].getRetainedWidth() > width)) {
                  width = other[i].getRetainedWidth();
              }
          }
          BorderInfo widest = null;
          int count = 0;
          //See if there's only one with the widest border
          for (int i = 0; i < current.length - 1; i++) {
              if ((current[i] != null) && (current[i].getRetainedWidth() == 
width)) {
                  count++;
                  if (widest == null) {
                      widest = current[i];
                  }
                  break;
              } else {
                  current[i] = null; //Discard the narrower ones
              }
              if ((other[i] != null) && (other[i].getRetainedWidth() == width)) 
{
                  count++;
                  if (widest == null) {
                      widest = other[i];
                  }
                  break;
              } else {
                  other[i] = null; //Discard the narrower ones
              }
          }
          if (count == 1) {
              return widest;
          } else {
              return null;
          }
      }
  
      private BorderInfo doRule4(BorderInfo[] current, BorderInfo[] other) {
          int pref = getPreferenceValue(Constants.EN_INSET); //Lowest preference
          //Find highest preference value
          for (int i = 0; i < current.length - 1; i++) {
              if (current[i] != null) {
                  int currPref = getPreferenceValue(current[i].getStyle());
                  if (currPref > pref) {
                      pref = currPref;
                      break;
                  }
              }
              if (other[i] != null) {
                  int currPref = getPreferenceValue(other[i].getStyle());
                  if (currPref > pref) {
                      pref = currPref;
                      break;
                  }
              }
          }
          BorderInfo preferred = null;
          int count = 0;
          //See if there's only one with the preferred border style
          for (int i = 0; i < current.length - 1; i++) {
              if (current[i] != null) {
                  int currPref = getPreferenceValue(current[i].getStyle());
                  if (currPref == pref) {
                      count++;
                      if (preferred == null) {
                          preferred = current[i];
                      }
                      break;
                  }
              } else {
                  current[i] = null; //Discard the ones that are not preferred
              }
              if (other[i] != null) {
                  int currPref = getPreferenceValue(other[i].getStyle());
                  if (currPref == pref) {
                      count++;
                      if (preferred == null) {
                          preferred = other[i];
                      }
                      break;
                  }
              } else {
                  other[i] = null; //Discard the ones that are not preferred
              }
          }
          if (count == 1) {
              return preferred;
          } else {
              return null;
          }
      }
  
      private BorderInfo doRule5(BorderInfo[] current, BorderInfo[] other) {
          for (int i = 0; i < current.length - 1; i++) {
              if (current[i] != null) {
                  return current[i];
              }
              if (other[i] != null) {
                  return other[i];
              }
          }
          return null;
      }
  
  }
  
  
  
  1.1                  
xml-fop/src/java/org/apache/fop/layoutmgr/table/CollapsingBorderModel.java
  
  Index: CollapsingBorderModel.java
  ===================================================================
  /*
   * Copyright 2005 The Apache Software Foundation.
   *
   * Licensed 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: CollapsingBorderModel.java,v 1.1 2005/02/21 21:52:14 jeremias Exp $ */
  
  package org.apache.fop.layoutmgr.table;
  
  import org.apache.fop.fo.Constants;
  import org.apache.fop.fo.properties.CommonBorderPaddingBackground;
  import org.apache.fop.fo.properties.CommonBorderPaddingBackground.BorderInfo;
  
  /**
   * This class is a superclass for the two collapsing border models defined
   * in the XSL 1.0 specification.
   */
  public abstract class CollapsingBorderModel {
  
      /** Indicates that the cell is/starts in the first row being painted on a 
particular page */
      public static final int FIRST_ROW_IN_TABLE_PART = 1;
      /** Indicates that the cell is/ends in the last row being painted on a 
particular page */
      public static final int LAST_ROW_IN_TABLE_PART  = 2;
      /** Indicates that the cell is/starts in the first row of a 
body/table-header/table-footer */
      public static final int FIRST_ROW_IN_GROUP      = 4;
      /** Indicates that the cell is/end in the last row of a 
body/table-header/table-footer */
      public static final int LAST_ROW_IN_GROUP       = 8;
      
      private static CollapsingBorderModel collapse = null;
      private static CollapsingBorderModel collapseWithPrecedence = null;
      
      /**
       * @param cellLM the cell
       * @return the border model for the cell
       */
      public static CollapsingBorderModel getBorderModelFor(int borderCollapse) 
{
          switch (borderCollapse) {
              case Constants.EN_COLLAPSE:
                  if (collapse == null) {
                      collapse = new CollapsingBorderModelEyeCatching();
                  }
                  return collapse;
              case Constants.EN_COLLAPSE_WITH_PRECEDENCE:
                  if (collapseWithPrecedence == null) {
                      //collapseWithPrecedence = new 
CollapsingBorderModelWithPrecedence();
                  }
                  return collapseWithPrecedence;
              default:
                  throw new IllegalArgumentException("Illegal border-collapse 
mode.");
          }
      }
      
      /**
       * @param side the side on the current cell
       * @return the adjacent side on the neighbouring cell
       */
      public static int getOtherSide(int side) {
          switch (side) {
              case CommonBorderPaddingBackground.BEFORE:
                  return CommonBorderPaddingBackground.AFTER;
              case CommonBorderPaddingBackground.AFTER:
                  return CommonBorderPaddingBackground.BEFORE;
              case CommonBorderPaddingBackground.START:
                  return CommonBorderPaddingBackground.END;
              case CommonBorderPaddingBackground.END:
                  return CommonBorderPaddingBackground.START;
              default:
                  throw new IllegalArgumentException("Illegal parameter: side");
          }
      }
      
      /**
       * @param side the side to investigate
       * @return true if the adjacent cell is before or after
       */
      protected boolean isVerticalRelation(int side) {
          return (side == CommonBorderPaddingBackground.BEFORE 
                  || side == CommonBorderPaddingBackground.AFTER);
      }
  
      
      /**
       * See rule 4 in 6.7.10 for the collapsing border model.
       * @param style the border style to get the preference value for
       * @return the preference value of the style
       */
      public int getPreferenceValue(int style) {
          switch (style) {
              case Constants.EN_DOUBLE: return 0;
              case Constants.EN_SOLID: return -1;
              case Constants.EN_DASHED: return -2;
              case Constants.EN_DOTTED: return -3;
              case Constants.EN_RIDGE: return -4;
              case Constants.EN_OUTSET: return -5;
              case Constants.EN_GROOVE: return -6;
              case Constants.EN_INSET: return -6;
              default: throw new IllegalStateException("Illegal border style: " 
+ style);
          }
      }
      
      /**
       * Determines the winning BorderInfo.
       * @param current cell info of the current element
       * @param neighbour cell info of the neighbouring element
       * @return the winning BorderInfo
       */
      public abstract BorderInfo determineWinner(
              GridUnit current, GridUnit neighbour, int side, int flags);
      
  }
  
  
  
  1.1                  
xml-fop/src/java/org/apache/fop/layoutmgr/table/GridUnit.java
  
  Index: GridUnit.java
  ===================================================================
  /*
   * Copyright 2005 The Apache Software Foundation.
   *
   * Licensed 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: GridUnit.java,v 1.1 2005/02/21 21:52:14 jeremias Exp $ */
  
  package org.apache.fop.layoutmgr.table;
  
  import org.apache.fop.fo.flow.Table;
  import org.apache.fop.fo.properties.CommonBorderPaddingBackground;
  import org.apache.fop.fo.properties.CommonBorderPaddingBackground.BorderInfo;
  
  
  public class GridUnit {
      
      /** layout manager for the cell occupying this grid unit, may be null */
      public Cell layoutManager;
      /** layout manager for the column that this grid unit belongs to */
      public Column column;
      /** layout manager for the row that this grid unit belongs to */
      public Row row;
      /** index of grid unit within cell in column direction */
      public int colSpanIndex;
      /** index of grid unit within cell in row direction */
      public int rowSpanIndex;
      /** effective borders for a cell slot (used for collapsing border model) 
*/
      public CommonBorderPaddingBackground effBorders;
      
      public GridUnit(Cell layoutManager, int colSpanIndex) {
          this.layoutManager = layoutManager;
          this.colSpanIndex = colSpanIndex;
          this.rowSpanIndex = 0;
      }
      
      public GridUnit(Cell layoutManager) {
          this(layoutManager, 0);
      }
  
      /** @return true if the grid unit is the primary of a cell */
      public boolean isPrimaryGridUnit() {
          return (colSpanIndex == 0) && (rowSpanIndex == 0);
      }
      
      /** @return true if the grid unit is the last in column spanning 
direction */
      public boolean isLastGridUnitColSpan() {
          if (layoutManager != null) {
              return (colSpanIndex == 
layoutManager.getFObj().getNumberColumnsSpanned() - 1);
          } else {
              return true;
          }
      }
      
      /** @return true if the grid unit is the last in column spanning 
direction */
      public boolean isLastGridUnitRowSpan() {
          if (layoutManager != null) {
              return (rowSpanIndex == 
layoutManager.getFObj().getNumberRowsSpanned() - 1);
          } else {
              return true;
          }
      }
      
      /** @return true if the cell is part of a span in column direction */
      public boolean isColSpan() {
          return (colSpanIndex > 0);
      }
  
      public BorderInfo getOriginalBorderInfoForCell(int side) {
          if (layoutManager != null) {
              return 
layoutManager.getFObj().getCommonBorderPaddingBackground().getBorderInfo(side);
          } else {
              return null;
          }
      }
      
      /**
       * Assign the borders from the given cell to this cell info. Used in
       * case of separate border model.
       * @param current cell to take the borders from
       */
      public void assignBorder(Cell current) {
          if (current != null) {
              this.effBorders = 
current.getFObj().getCommonBorderPaddingBackground();
          }
      }
      
      /**
       * Assign the borders directly.
       * @param borders the borders to use
       */
      public void assignBorder(CommonBorderPaddingBackground borders) {
          if (borders != null) {
              this.effBorders = borders;
          }
      }
      
      /**
       * Resolve collapsing borders for the given cell and store the resulting
       * borders in this cell info. Use in case of the collapsing border model.
       * @param current cell to resolve borders for
       * @param before cell before the current cell, if any
       * @param after cell after the current cell, if any
       * @param start cell preceeding the current cell, if any
       * @param end cell succeeding of the current cell, if any
       */
      public static void resolveBorder(Table table,
              CommonBorderPaddingBackground target,
              GridUnit current, GridUnit other, int side) {
          if (current == null) {
              return;
          }
          
          CollapsingBorderModel borderModel = 
CollapsingBorderModel.getBorderModelFor(
                  table.getBorderCollapse());
          target.setBorderInfo(
                  borderModel.determineWinner(current, other, 
                          side, 0), side);
      }
      
  }
  
  
  1.37      +18 -0     xml-fop/src/java/org/apache/fop/fo/flow/TableBody.java
  
  Index: TableBody.java
  ===================================================================
  RCS file: /home/cvs/xml-fop/src/java/org/apache/fop/fo/flow/TableBody.java,v
  retrieving revision 1.36
  retrieving revision 1.37
  diff -u -r1.36 -r1.37
  --- TableBody.java    8 Feb 2005 09:20:41 -0000       1.36
  +++ TableBody.java    21 Feb 2005 21:52:14 -0000      1.37
  @@ -152,5 +152,23 @@
       public int getNameId() {
           return FO_TABLE_BODY;
       }
  +
  +    /**
  +     * @param obj table row in question
  +     * @return true if the given table row is the first row of this body.
  +     */
  +    public boolean isFirst(TableRow obj) {
  +        return (childNodes.size() > 0) 
  +            && (childNodes.get(0) == obj);
  +    }
  +
  +    /**
  +     * @param obj table row in question
  +     * @return true if the given table row is the first row of this body.
  +     */
  +    public boolean isLast(TableRow obj) {
  +        return (childNodes.size() > 0) 
  +            && (childNodes.get(childNodes.size() - 1) == obj);
  +    }
   }
   
  
  
  
  1.7       +6 -4      
xml-fop/src/java/org/apache/fop/layoutmgr/LayoutManagerMapping.java
  
  Index: LayoutManagerMapping.java
  ===================================================================
  RCS file: 
/home/cvs/xml-fop/src/java/org/apache/fop/layoutmgr/LayoutManagerMapping.java,v
  retrieving revision 1.6
  retrieving revision 1.7
  diff -u -r1.6 -r1.7
  --- LayoutManagerMapping.java 10 Feb 2005 19:40:47 -0000      1.6
  +++ LayoutManagerMapping.java 21 Feb 2005 21:52:14 -0000      1.7
  @@ -313,7 +313,7 @@
   
       public static class TableLayoutManagerMaker extends Maker {
           
  -        private List getColumnLayoutManagerList(Table table) {
  +        private List getColumnLayoutManagerList(Table table, 
TableLayoutManager tlm) {
               List columnLMs = null;
               List columns = table.getColumns();
               if (columns != null) {
  @@ -329,7 +329,9 @@
                           while (colnum > columnLMs.size()) {
                               columnLMs.add(null);
                           }
  -                        columnLMs.set(colnum - 1, new Column(col));
  +                        Column colLM = new Column(col);
  +                        colLM.setParent(tlm);
  +                        columnLMs.set(colnum - 1, colLM);
                           colnum++;
                       }
                   }
  @@ -350,7 +352,7 @@
           public void make(FONode node, List lms) {
               Table table = (Table) node;
               TableLayoutManager tlm = new TableLayoutManager(table);
  -            List columnLMs = getColumnLayoutManagerList(table);
  +            List columnLMs = getColumnLayoutManagerList(table, tlm);
               if (columnLMs != null) {
                   tlm.setColumns(columnLMs);
               }
  
  
  
  1.12      +62 -4     
xml-fop/src/java/org/apache/fop/fo/properties/CommonBorderPaddingBackground.java
  
  Index: CommonBorderPaddingBackground.java
  ===================================================================
  RCS file: 
/home/cvs/xml-fop/src/java/org/apache/fop/fo/properties/CommonBorderPaddingBackground.java,v
  retrieving revision 1.11
  retrieving revision 1.12
  diff -u -r1.11 -r1.12
  --- CommonBorderPaddingBackground.java        17 Feb 2005 13:40:42 -0000      
1.11
  +++ CommonBorderPaddingBackground.java        21 Feb 2005 21:52:14 -0000      
1.12
  @@ -75,7 +75,7 @@
       /** the "end" edge */ 
       public static final int END = 3;
   
  -    private static class BorderInfo implements Cloneable {
  +    public static class BorderInfo implements Cloneable {
           private int mStyle; // Enum for border style
           private ColorType mColor; // Border color
           private CondLengthProperty mWidth;
  @@ -85,6 +85,40 @@
               mWidth = width;
               mColor = color;
           }
  +        
  +        public int getStyle() {
  +            return this.mStyle;
  +        }
  +        
  +        public ColorType getColor() {
  +            return this.mColor;
  +        }
  +        
  +        public CondLengthProperty getWidth() {
  +            return this.mWidth;
  +        }
  +
  +        public int getRetainedWidth() {
  +            if ((mStyle == Constants.EN_NONE)
  +                    || (mStyle == Constants.EN_HIDDEN)) {
  +                return 0;
  +            } else {
  +                return mWidth.getLengthValue();
  +            }
  +        }
  +        
  +        /** @see java.lang.Object#toString() */
  +        public String toString() {
  +            StringBuffer sb = new StringBuffer("BorderInfo");
  +            sb.append(" {");
  +            sb.append(mStyle);
  +            sb.append(", ");
  +            sb.append(mColor);
  +            sb.append(", ");
  +            sb.append(mWidth);
  +            sb.append("}");
  +            return sb.toString();
  +        }
       }
   
       private BorderInfo[] borderInfo = new BorderInfo[4];
  @@ -92,6 +126,13 @@
   
       /**
        * Construct a CommonBorderPaddingBackground object.
  +     */
  +    public CommonBorderPaddingBackground() {
  +        
  +    }
  +    
  +    /**
  +     * Construct a CommonBorderPaddingBackground object.
        * @param pList The PropertyList to get properties from.
        * @param fobj The FO to create this instance for.
        * @throws PropertyException if there's an error while binding the 
properties
  @@ -159,13 +200,30 @@
           // If style = none, force width to 0, don't get Color (spec 7.7.20)
           int style = pList.get(styleProp).getEnum();
           if (style != Constants.EN_NONE) {
  -            borderInfo[side] = new BorderInfo(style, 
  +            setBorderInfo(new BorderInfo(style, 
                       pList.get(widthProp).getCondLength(), 
  -                    pList.get(colorProp).getColorType());
  +                    pList.get(colorProp).getColorType()), side);
           }
       }
       
       /**
  +     * Sets a border.
  +     * @param info the border information
  +     * @param side the side to apply the info to
  +     */
  +    public void setBorderInfo(BorderInfo info, int side) {
  +        this.borderInfo[side] = info;
  +    }
  +    
  +    /**
  +     * @param side the side to retrieve
  +     * @return the border info for a side
  +     */
  +    public BorderInfo getBorderInfo(int side) {
  +        return this.borderInfo[side];
  +    }
  +    
  +    /**
        * @return the background image as a preloaded FopImage, null if there is
        *     no background image.
        */
  
  
  

---------------------------------------------------------------------
To unsubscribe, e-mail: [EMAIL PROTECTED]
For additional commands, e-mail: [EMAIL PROTECTED]

Reply via email to