001: /*
002: * Licensed to the Apache Software Foundation (ASF) under one or more
003: * contributor license agreements. See the NOTICE file distributed with
004: * this work for additional information regarding copyright ownership.
005: * The ASF licenses this file to You under the Apache License, Version 2.0
006: * (the "License"); you may not use this file except in compliance with
007: * the License. You may obtain a copy of the License at
008: *
009: * http://www.apache.org/licenses/LICENSE-2.0
010: *
011: * Unless required by applicable law or agreed to in writing, software
012: * distributed under the License is distributed on an "AS IS" BASIS,
013: * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
014: * See the License for the specific language governing permissions and
015: * limitations under the License.
016: */
017:
018: /* $Id: CollapsingBorderModelEyeCatching.java 478928 2006-11-24 17:32:48Z vhennebert $ */
019:
020: package org.apache.fop.layoutmgr.table;
021:
022: import org.apache.fop.fo.Constants;
023: import org.apache.fop.fo.flow.Table;
024: import org.apache.fop.fo.flow.TableBody;
025: import org.apache.fop.fo.flow.TableCell;
026: import org.apache.fop.fo.flow.TableColumn;
027: import org.apache.fop.fo.flow.TableRow;
028: import org.apache.fop.fo.properties.CommonBorderPaddingBackground.BorderInfo;
029:
030: /**
031: * Implements the normal "collapse" border model defined in 6.7.10 in XSL 1.0.
032: *
033: * TODO Column groups are not yet checked in this algorithm!
034: */
035: public class CollapsingBorderModelEyeCatching extends
036: CollapsingBorderModel {
037:
038: public BorderInfo determineWinner(GridUnit currentGridUnit,
039: GridUnit otherGridUnit, int side, int flags) {
040: final boolean vertical = isVerticalRelation(side);
041: final int otherSide = getOtherSide(side);
042:
043: //Get cells
044: TableCell currentCell = currentGridUnit.getCell();
045: TableCell otherCell = null;
046: if (otherGridUnit != null) {
047: otherCell = otherGridUnit.getCell();
048: }
049:
050: //Get rows
051: TableRow currentRow = currentGridUnit.getRow();
052: TableRow otherRow = null;
053: if (vertical && otherCell != null) {
054: otherRow = otherGridUnit.getRow();
055: }
056:
057: //get bodies
058: TableBody currentBody = currentGridUnit.getBody();
059: TableBody otherBody = null;
060: if (otherRow != null) {
061: otherBody = otherGridUnit.getBody();
062: }
063:
064: //get columns
065: TableColumn currentColumn = currentGridUnit.getColumn();
066: TableColumn otherColumn = null;
067: if (otherGridUnit != null) {
068: otherColumn = otherGridUnit.getColumn();
069: }
070:
071: //TODO get column groups
072:
073: //Get table
074: Table table = currentGridUnit.getTable();
075:
076: //----------------------------------------------------------------------
077: //We're creating two arrays containing the applicable BorderInfos for
078: //each cell in question.
079: //0 = cell, 1 = row, 2 = row group (body), 3 = column,
080: //4 = col group (spanned column, see 6.7.3), 5 = table
081:
082: BorderInfo[] current = new BorderInfo[6];
083: BorderInfo[] other = new BorderInfo[6];
084: //cell
085: current[0] = currentGridUnit.getOriginalBorderInfoForCell(side);
086: if (otherGridUnit != null) {
087: other[0] = otherGridUnit
088: .getOriginalBorderInfoForCell(otherSide);
089: }
090: if ((currentRow != null)
091: && (side == BEFORE
092: || side == AFTER
093: || (currentGridUnit
094: .getFlag(GridUnit.IN_FIRST_COLUMN) && side == START) || (currentGridUnit
095: .getFlag(GridUnit.IN_LAST_COLUMN) && side == END))) {
096: //row
097: current[1] = currentRow.getCommonBorderPaddingBackground()
098: .getBorderInfo(side);
099: }
100: if (otherRow != null) {
101: //row
102: other[1] = otherRow.getCommonBorderPaddingBackground()
103: .getBorderInfo(otherSide);
104: }
105: if (currentBody != null
106: && ((side == BEFORE && currentGridUnit
107: .getFlag(GridUnit.FIRST_IN_PART))
108: || (side == AFTER && currentGridUnit
109: .getFlag(GridUnit.LAST_IN_PART))
110: || (currentGridUnit
111: .getFlag(GridUnit.IN_FIRST_COLUMN) && side == START) || (currentGridUnit
112: .getFlag(GridUnit.IN_LAST_COLUMN) && side == END))) {
113: //row group (=body, table-header or table-footer)
114: current[2] = currentBody.getCommonBorderPaddingBackground()
115: .getBorderInfo(side);
116: }
117: if (otherGridUnit != null
118: && otherBody != null
119: && ((otherSide == BEFORE && otherGridUnit
120: .getFlag(GridUnit.FIRST_IN_PART)) || (otherSide == AFTER && otherGridUnit
121: .getFlag(GridUnit.LAST_IN_PART)))) {
122: //row group (=body, table-header or table-footer)
123: other[2] = otherBody.getCommonBorderPaddingBackground()
124: .getBorderInfo(otherSide);
125: }
126: if ((side == BEFORE && otherGridUnit == null)
127: || (side == AFTER && otherGridUnit == null)
128: || (side == START) || (side == END)) {
129: //column
130: current[3] = currentColumn
131: .getCommonBorderPaddingBackground().getBorderInfo(
132: side);
133: }
134: if (otherColumn != null) {
135: //column
136: other[3] = otherColumn.getCommonBorderPaddingBackground()
137: .getBorderInfo(otherSide);
138: }
139: //TODO current[4] and other[4] for column groups
140: if (otherGridUnit == null
141: && ((side == BEFORE && (flags & VERTICAL_START_END_OF_TABLE) > 0)
142: || (side == AFTER && (flags & VERTICAL_START_END_OF_TABLE) > 0)
143: || (side == START) || (side == END))) {
144: //table
145: current[5] = table.getCommonBorderPaddingBackground()
146: .getBorderInfo(side);
147: }
148: //other[6] is always null, since it's always the same table
149:
150: BorderInfo resolved = null;
151:
152: // *** Rule 1 ***
153: resolved = doRule1(current, other);
154: if (resolved != null) {
155: return resolved;
156: }
157:
158: // *** Rule 2 ***
159: if (!doRule2(current, other)) {
160: }
161:
162: // *** Rule 3 ***
163: resolved = doRule3(current, other);
164: if (resolved != null) {
165: return resolved;
166: }
167:
168: // *** Rule 4 ***
169: resolved = doRule4(current, other);
170: if (resolved != null) {
171: return resolved;
172: }
173:
174: // *** Rule 5 ***
175: resolved = doRule5(current, other);
176: if (resolved != null) {
177: return resolved;
178: }
179:
180: return null; //no winner, no border
181: }
182:
183: private BorderInfo doRule1(BorderInfo[] current, BorderInfo[] other) {
184: for (int i = 0; i < current.length; i++) {
185: if ((current[i] != null)
186: && (current[i].getStyle() == Constants.EN_HIDDEN)) {
187: return current[i];
188: }
189: if ((other[i] != null)
190: && (other[i].getStyle() == Constants.EN_HIDDEN)) {
191: return other[i];
192: }
193: }
194: return null;
195: }
196:
197: private boolean doRule2(BorderInfo[] current, BorderInfo[] other) {
198: boolean found = false;
199: for (int i = 0; i < current.length; i++) {
200: if ((current[i] != null)
201: && (current[i].getStyle() != Constants.EN_NONE)) {
202: found = true;
203: break;
204: }
205: if ((other[i] != null)
206: && (other[i].getStyle() != Constants.EN_NONE)) {
207: found = true;
208: break;
209: }
210: }
211: return found;
212: }
213:
214: private BorderInfo doRule3(BorderInfo[] current, BorderInfo[] other) {
215: int width = 0;
216: //Find max border width
217: for (int i = 0; i < current.length; i++) {
218: if ((current[i] != null)
219: && (current[i].getRetainedWidth() > width)) {
220: width = current[i].getRetainedWidth();
221: }
222: if ((other[i] != null)
223: && (other[i].getRetainedWidth() > width)) {
224: width = other[i].getRetainedWidth();
225: }
226: }
227: BorderInfo widest = null;
228: int count = 0;
229: //See if there's only one with the widest border
230: for (int i = 0; i < current.length; i++) {
231: if ((current[i] != null)
232: && (current[i].getRetainedWidth() == width)) {
233: count++;
234: if (widest == null) {
235: widest = current[i];
236: }
237: } else {
238: current[i] = null; //Discard the narrower ones
239: }
240: if ((other[i] != null)
241: && (other[i].getRetainedWidth() == width)) {
242: count++;
243: if (widest == null) {
244: widest = other[i];
245: }
246: } else {
247: other[i] = null; //Discard the narrower ones
248: }
249: }
250: if (count == 1) {
251: return widest;
252: } else {
253: return null;
254: }
255: }
256:
257: private BorderInfo doRule4(BorderInfo[] current, BorderInfo[] other) {
258: int pref = getPreferenceValue(Constants.EN_INSET); //Lowest preference
259: //Find highest preference value
260: for (int i = 0; i < current.length; i++) {
261: if (current[i] != null) {
262: int currPref = getPreferenceValue(current[i].getStyle());
263: if (currPref > pref) {
264: pref = currPref;
265: }
266: }
267: if (other[i] != null) {
268: int currPref = getPreferenceValue(other[i].getStyle());
269: if (currPref > pref) {
270: pref = currPref;
271: }
272: }
273: }
274: BorderInfo preferred = null;
275: int count = 0;
276: //See if there's only one with the preferred border style
277: for (int i = 0; i < current.length; i++) {
278: if (current[i] != null) {
279: int currPref = getPreferenceValue(current[i].getStyle());
280: if (currPref == pref) {
281: count++;
282: if (preferred == null) {
283: preferred = current[i];
284: }
285: break;
286: }
287: } else {
288: current[i] = null; //Discard the ones that are not preferred
289: }
290: if (other[i] != null) {
291: int currPref = getPreferenceValue(other[i].getStyle());
292: if (currPref == pref) {
293: count++;
294: if (preferred == null) {
295: preferred = other[i];
296: }
297: break;
298: }
299: } else {
300: other[i] = null; //Discard the ones that are not preferred
301: }
302: }
303: if (count == 1) {
304: return preferred;
305: } else {
306: return null;
307: }
308: }
309:
310: private BorderInfo doRule5(BorderInfo[] current, BorderInfo[] other) {
311: for (int i = 0; i < current.length; i++) {
312: if (current[i] != null) {
313: return current[i];
314: }
315: if (other[i] != null) {
316: return other[i];
317: }
318: }
319: return null;
320: }
321:
322: }
|