1 /*
2  * Licensed to the Apache Software Foundation (ASF) under one or more
3  * contributor license agreements.  See the NOTICE file distributed with
4  * this work for additional information regarding copyright ownership.
5  * The ASF licenses this file to You under the Apache License, Version 2.0
6  * (the "License"); you may not use this file except in compliance with
7  * the License.  You may obtain a copy of the License at
8  *
9  *      http://www.apache.org/licenses/LICENSE-2.0
10  *
11  * Unless required by applicable law or agreed to in writing, software
12  * distributed under the License is distributed on an "AS IS" BASIS,
13  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14  * See the License for the specific language governing permissions and
15  * limitations under the License.
16  */
17 
18 /* $Id: CollapsingBorderModel.java 1617052 2014-08-10 06:55:01Z gadams $ */
19 
20 package org.apache.fop.layoutmgr.table;
21 
22 import org.apache.fop.fo.Constants;
23 import org.apache.fop.fo.flow.table.BorderSpecification;
24 import org.apache.fop.fo.properties.CommonBorderPaddingBackground;
25 
26 /**
27  * This class is a superclass for the two collapsing border models defined
28  * in the XSL 1.0 specification.
29  */
30 public abstract class CollapsingBorderModel {
31 
32     /** before side */
33     protected static final int BEFORE = CommonBorderPaddingBackground.BEFORE;
34     /** after side */
35     protected static final int AFTER = CommonBorderPaddingBackground.AFTER;
36     /** start side */
37     protected static final int START = CommonBorderPaddingBackground.START;
38     /** end side */
39     protected static final int END = CommonBorderPaddingBackground.END;
40 
41     /** Indicates that the cell is/starts in the first row being painted on a particular page */
42     //public static final int FIRST_ROW_IN_TABLE_PART = 1;
43     /** Indicates that the cell is/ends in the last row being painted on a particular page */
44     //public static final int LAST_ROW_IN_TABLE_PART  = 2;
45     /** Indicates that the cell is/starts in the first row of a body/table-header/table-footer */
46     //public static final int FIRST_ROW_IN_GROUP      = 4;
47     /** Indicates that the cell is/end in the last row of a body/table-header/table-footer */
48     //public static final int LAST_ROW_IN_GROUP       = 8;
49 
50     private static CollapsingBorderModel collapse = new CollapsingBorderModelEyeCatching();
51     // private static CollapsingBorderModel collapseWithPrecedence = null;
52 
53     /**
54      * @param borderCollapse border collapse control
55      * @return the border model for the cell
56      */
getBorderModelFor(int borderCollapse)57     public static CollapsingBorderModel getBorderModelFor(int borderCollapse) {
58         switch (borderCollapse) {
59             case Constants.EN_COLLAPSE:
60                 return collapse;
61             case Constants.EN_COLLAPSE_WITH_PRECEDENCE:
62                 throw new UnsupportedOperationException("collapse-with-precedence not yet supported");
63             default:
64                 throw new IllegalArgumentException("Illegal border-collapse mode.");
65         }
66     }
67 
68     /**
69      * @param side the side on the current cell
70      * @return the adjacent side on the neighbouring cell
71      */
getOtherSide(int side)72     public/*TODO*/ static int getOtherSide(int side) {
73         switch (side) {
74             case CommonBorderPaddingBackground.BEFORE:
75                 return CommonBorderPaddingBackground.AFTER;
76             case CommonBorderPaddingBackground.AFTER:
77                 return CommonBorderPaddingBackground.BEFORE;
78             case CommonBorderPaddingBackground.START:
79                 return CommonBorderPaddingBackground.END;
80             case CommonBorderPaddingBackground.END:
81                 return CommonBorderPaddingBackground.START;
82             default:
83                 throw new IllegalArgumentException("Illegal parameter: side");
84         }
85     }
86 
87     /**
88      * @param side the side to investigate
89      * @return true if the adjacent cell is before or after
90      */
isVerticalRelation(int side)91     protected boolean isVerticalRelation(int side) {
92         return (side == CommonBorderPaddingBackground.BEFORE
93                 || side == CommonBorderPaddingBackground.AFTER);
94     }
95 
compareInt(int value1, int value2)96     private static int compareInt(int value1, int value2) {
97         if (value1 < value2) {
98             return -1;
99         } else if (value1 == value2) {
100             return 0;
101         } else {
102             return 1;
103         }
104     }
105 
106     /**
107      * See rule 4 in 6.7.10 for the collapsing border model.
108      * @param style the border style to get the preference value for
109      * @return the preference value of the style
110      */
getStylePreferenceValue(int style)111     private static int getStylePreferenceValue(int style) {
112         switch (style) {
113             case Constants.EN_DOUBLE: return 0;
114             case Constants.EN_SOLID: return -1;
115             case Constants.EN_DASHED: return -2;
116             case Constants.EN_DOTTED: return -3;
117             case Constants.EN_RIDGE: return -4;
118             case Constants.EN_OUTSET: return -5;
119             case Constants.EN_GROOVE: return -6;
120             case Constants.EN_INSET: return -7;
121             default: throw new IllegalStateException("Illegal border style: " + style);
122         }
123     }
124 
125     /**
126      * Compares the two given styles (see {@link Constants}).
127      *
128      * @param style1 a style constant
129      * @param style2 another style constant
130      * @return a value &lt; 0 if style1 has less priority than style2, 0 if both are
131      * equal, a value &gt; 0 if style1 has more priority than style2
132      */
compareStyles(int style1, int style2)133     static int compareStyles(int style1, int style2) {
134         int value1 = getStylePreferenceValue(style1);
135         int value2 = getStylePreferenceValue(style2);
136         return compareInt(value1, value2);
137     }
138 
getHolderPreferenceValue(int id)139     private static int getHolderPreferenceValue(int id) {
140         switch (id) {
141         case Constants.FO_TABLE_CELL: return 0;
142         case Constants.FO_TABLE_ROW: return -1;
143         case Constants.FO_TABLE_HEADER:
144         case Constants.FO_TABLE_FOOTER:
145         case Constants.FO_TABLE_BODY:
146             return -2;
147         case Constants.FO_TABLE_COLUMN: return -3;
148         // TODO colgroup
149         case Constants.FO_TABLE: return -4;
150         default: throw new IllegalStateException();
151         }
152     }
153 
154     /**
155      * Compares the two given FO ids ({@link Constants}.FO*) in terms of border
156      * declaration.
157      *
158      * @param id1 a FO id ({@link Constants#FO_TABLE}, {@link Constants#FO_TABLE_BODY},
159      * etc.)
160      * @param id2 another FO id
161      * @return a value &lt; 0 if id1 has less priority than id2, 0 if both are equal, a
162      * value &gt; 0 if id1 has more priority than id2
163      */
compareFOs(int id1, int id2)164     static int compareFOs(int id1, int id2) {
165         int p1 = getHolderPreferenceValue(id1);
166         int p2 = getHolderPreferenceValue(id2);
167         return compareInt(p1, p2);
168     }
169 
170     /**
171      * Returns the border which wins the border conflict resolution. In case the two
172      * borders are equivalent (identical, or only the color is different), null is
173      * returned.
174      *
175      * @param border1 a border specification
176      * @param border2 another border specification
177      * @param discard true if the .conditionality component of the border width must be
178      * taken into account
179      * @return the winning border, null if the two borders are equivalent
180      */
determineWinner(BorderSpecification border1, BorderSpecification border2, boolean discard)181     public abstract BorderSpecification determineWinner(BorderSpecification border1,
182             BorderSpecification border2, boolean discard);
183 
184     /**
185      * Returns the border which wins the border conflict resolution. Same as
186      * {@link #determineWinner(BorderSpecification, BorderSpecification, boolean)
187      * determineWinner(border1, border2, false)}.
188      *
189      * @param border1 a border specification
190      * @param border2 another border specification
191      * @return the winning border, null if the two borders are equivalent
192      * @see #determineWinner(BorderSpecification,BorderSpecification,boolean)
193      */
determineWinner(BorderSpecification border1, BorderSpecification border2)194     public abstract BorderSpecification determineWinner(BorderSpecification border1,
195             BorderSpecification border2);
196 
197 }
198