Ви не можете вибрати більше 25 тем Теми мають розпочинатися з літери або цифри, можуть містити дефіси (-) і не повинні перевищувати 35 символів.

RowGroupLayoutManager.java 11KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230
  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. /* $Id$ */
  18. package org.apache.fop.layoutmgr.table;
  19. import java.util.LinkedList;
  20. import java.util.List;
  21. import org.apache.commons.logging.Log;
  22. import org.apache.commons.logging.LogFactory;
  23. import org.apache.fop.fo.Constants;
  24. import org.apache.fop.fo.FONode;
  25. import org.apache.fop.fo.flow.table.EffRow;
  26. import org.apache.fop.fo.flow.table.GridUnit;
  27. import org.apache.fop.fo.flow.table.PrimaryGridUnit;
  28. import org.apache.fop.fo.flow.table.TableRow;
  29. import org.apache.fop.fo.properties.CommonBorderPaddingBackground;
  30. import org.apache.fop.fo.properties.LengthRangeProperty;
  31. import org.apache.fop.layoutmgr.ElementListObserver;
  32. import org.apache.fop.layoutmgr.LayoutContext;
  33. import org.apache.fop.layoutmgr.MinOptMaxUtil;
  34. import org.apache.fop.traits.MinOptMax;
  35. import org.apache.fop.util.BreakUtil;
  36. class RowGroupLayoutManager {
  37. private static Log log = LogFactory.getLog(RowGroupLayoutManager.class);
  38. private EffRow[] rowGroup;
  39. private TableLayoutManager tableLM;
  40. private TableStepper tableStepper;
  41. RowGroupLayoutManager(TableLayoutManager tableLM, EffRow[] rowGroup,
  42. TableStepper tableStepper) {
  43. this.tableLM = tableLM;
  44. this.rowGroup = rowGroup;
  45. this.tableStepper = tableStepper;
  46. }
  47. public LinkedList getNextKnuthElements(LayoutContext context, int alignment, int bodyType) {
  48. LinkedList returnList = new LinkedList();
  49. createElementsForRowGroup(context, alignment, bodyType, returnList);
  50. context.setFlags(LayoutContext.KEEP_WITH_PREVIOUS_PENDING,
  51. rowGroup[0].mustKeepWithPrevious());
  52. context.setFlags(LayoutContext.KEEP_WITH_NEXT_PENDING,
  53. rowGroup[rowGroup.length - 1].mustKeepWithNext());
  54. int breakBefore = Constants.EN_AUTO;
  55. TableRow firstRow = rowGroup[0].getTableRow();
  56. if (firstRow != null) {
  57. breakBefore = firstRow.getBreakBefore();
  58. }
  59. context.setBreakBefore(BreakUtil.compareBreakClasses(breakBefore,
  60. rowGroup[0].getBreakBefore()));
  61. int breakAfter = Constants.EN_AUTO;
  62. TableRow lastRow = rowGroup[rowGroup.length - 1].getTableRow();
  63. if (lastRow != null) {
  64. breakAfter = lastRow.getBreakAfter();
  65. }
  66. context.setBreakAfter(BreakUtil.compareBreakClasses(breakAfter,
  67. rowGroup[rowGroup.length - 1].getBreakAfter()));
  68. return returnList;
  69. }
  70. /**
  71. * Creates Knuth elements for a row group (see TableRowIterator.getNextRowGroup()).
  72. * @param context Active LayoutContext
  73. * @param alignment alignment indicator
  74. * @param bodyType Indicates what kind of body is being processed (BODY, HEADER or FOOTER)
  75. * @param returnList List to received the generated elements
  76. * @param rowGroup row group to process
  77. */
  78. private void createElementsForRowGroup(LayoutContext context, int alignment,
  79. int bodyType, LinkedList returnList) {
  80. log.debug("Handling row group with " + rowGroup.length + " rows...");
  81. MinOptMax[] rowHeights = new MinOptMax[rowGroup.length];
  82. MinOptMax[] explicitRowHeights = new MinOptMax[rowGroup.length];
  83. EffRow row;
  84. List pgus = new java.util.ArrayList(); //holds a list of a row's primary grid units
  85. for (int rgi = 0; rgi < rowGroup.length; rgi++) {
  86. row = rowGroup[rgi];
  87. rowHeights[rgi] = new MinOptMax(0, 0, Integer.MAX_VALUE);
  88. explicitRowHeights[rgi] = new MinOptMax(0, 0, Integer.MAX_VALUE);
  89. pgus.clear();
  90. TableRow tableRow = null;
  91. // The row's minimum content height; 0 if the row's height is auto, otherwise
  92. // the .minimum component of the explicitly specified value
  93. int minRowBPD = 0;
  94. // The BPD of the biggest cell in the row
  95. int maxCellBPD = 0;
  96. for (int j = 0; j < row.getGridUnits().size(); j++) {
  97. GridUnit gu = row.getGridUnit(j);
  98. if ((gu.isPrimary() || (gu.getColSpanIndex() == 0 && gu.isLastGridUnitRowSpan()))
  99. && !gu.isEmpty()) {
  100. PrimaryGridUnit primary = gu.getPrimary();
  101. if (gu.isPrimary()) {
  102. // TODO a new LM must be created for every new static-content
  103. primary.createCellLM();
  104. primary.getCellLM().setParent(tableLM);
  105. //Determine the table-row if any
  106. if (tableRow == null && primary.getRow() != null) {
  107. tableRow = primary.getRow();
  108. //Check for bpd on row, see CSS21, 17.5.3 Table height algorithms
  109. LengthRangeProperty rowBPD = tableRow.getBlockProgressionDimension();
  110. if (!rowBPD.getMinimum(tableLM).isAuto()) {
  111. minRowBPD = Math.max(minRowBPD,
  112. rowBPD.getMinimum(tableLM).getLength().getValue(tableLM));
  113. }
  114. MinOptMaxUtil.restrict(explicitRowHeights[rgi], rowBPD, tableLM);
  115. }
  116. //Calculate width of cell
  117. int spanWidth = 0;
  118. for (int i = primary.getColIndex();
  119. i < primary.getColIndex()
  120. + primary.getCell().getNumberColumnsSpanned();
  121. i++) {
  122. if (tableLM.getColumns().getColumn(i + 1) != null) {
  123. spanWidth += tableLM.getColumns().getColumn(i + 1)
  124. .getColumnWidth().getValue(tableLM);
  125. }
  126. }
  127. LayoutContext childLC = new LayoutContext(0);
  128. childLC.setStackLimit(context.getStackLimit()); //necessary?
  129. childLC.setRefIPD(spanWidth);
  130. //Get the element list for the cell contents
  131. LinkedList elems = primary.getCellLM().getNextKnuthElements(
  132. childLC, alignment);
  133. ElementListObserver.observe(elems, "table-cell", primary.getCell().getId());
  134. primary.setElements(elems);
  135. }
  136. //Calculate height of row, see CSS21, 17.5.3 Table height algorithms
  137. if (gu.isLastGridUnitRowSpan()) {
  138. // The effective cell's bpd, after taking into account bpd
  139. // (possibly explicitly) set on the row or on the cell, and the
  140. // cell's content length
  141. int effectiveCellBPD = minRowBPD;
  142. LengthRangeProperty cellBPD = primary.getCell()
  143. .getBlockProgressionDimension();
  144. if (!cellBPD.getMinimum(tableLM).isAuto()) {
  145. effectiveCellBPD = Math.max(effectiveCellBPD,
  146. cellBPD.getMinimum(tableLM).getLength().getValue(tableLM));
  147. }
  148. if (!cellBPD.getOptimum(tableLM).isAuto()) {
  149. effectiveCellBPD = Math.max(effectiveCellBPD,
  150. cellBPD.getOptimum(tableLM).getLength().getValue(tableLM));
  151. }
  152. if (gu.getRowSpanIndex() == 0) {
  153. //TODO ATM only non-row-spanned cells are taken for this
  154. MinOptMaxUtil.restrict(explicitRowHeights[rgi], cellBPD, tableLM);
  155. }
  156. effectiveCellBPD = Math.max(effectiveCellBPD,
  157. primary.getContentLength());
  158. int borderWidths = primary.getBeforeAfterBorderWidth();
  159. int padding = 0;
  160. maxCellBPD = Math.max(maxCellBPD, effectiveCellBPD);
  161. CommonBorderPaddingBackground cbpb
  162. = primary.getCell().getCommonBorderPaddingBackground();
  163. padding += cbpb.getPaddingBefore(false, primary.getCellLM());
  164. padding += cbpb.getPaddingAfter(false, primary.getCellLM());
  165. int effRowHeight = effectiveCellBPD
  166. + padding + borderWidths;
  167. for (int previous = 0; previous < gu.getRowSpanIndex(); previous++) {
  168. effRowHeight -= rowHeights[rgi - previous - 1].opt;
  169. }
  170. if (effRowHeight > rowHeights[rgi].min) {
  171. //This is the new height of the (grid) row
  172. MinOptMaxUtil.extendMinimum(rowHeights[rgi], effRowHeight, false);
  173. }
  174. }
  175. if (gu.isPrimary()) {
  176. pgus.add(primary);
  177. }
  178. }
  179. }
  180. row.setHeight(rowHeights[rgi]);
  181. row.setExplicitHeight(explicitRowHeights[rgi]);
  182. if (maxCellBPD > row.getExplicitHeight().max) {
  183. log.warn(FONode.decorateWithContextInfo(
  184. "The contents of row " + (row.getIndex() + 1)
  185. + " are taller than they should be (there is a"
  186. + " block-progression-dimension or height constraint on the indicated row)."
  187. + " Due to its contents the row grows"
  188. + " to " + maxCellBPD + " millipoints, but the row shouldn't get"
  189. + " any taller than " + row.getExplicitHeight() + " millipoints.",
  190. row.getTableRow()));
  191. }
  192. }
  193. if (log.isDebugEnabled()) {
  194. log.debug("rowGroup:");
  195. for (int i = 0; i < rowHeights.length; i++) {
  196. log.debug(" height=" + rowHeights[i] + " explicit=" + explicitRowHeights[i]);
  197. }
  198. }
  199. LinkedList elements = tableStepper.getCombinedKnuthElementsForRowGroup(context,
  200. rowGroup, bodyType);
  201. returnList.addAll(elements);
  202. }
  203. }