You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

ActiveCell.java 9.2KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243
  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.List;
  20. import org.apache.fop.layoutmgr.ElementListUtils;
  21. import org.apache.fop.layoutmgr.KnuthBox;
  22. import org.apache.fop.layoutmgr.KnuthElement;
  23. import org.apache.fop.layoutmgr.KnuthPenalty;
  24. class ActiveCell {
  25. private PrimaryGridUnit pgu;
  26. /** Knuth elements for this active cell. */
  27. private List elementList;
  28. private boolean prevIsBox = false;
  29. /** Number of the row where the row-span ends, zero-based. */
  30. private int endRow;
  31. /** Index, in the list of Knuth elements, of the element starting the current step. */
  32. private int start;
  33. /** Index, in the list of Knuth elements, of the element ending the current step. */
  34. private int end;
  35. /**
  36. * Total length of the Knuth elements already included in the steps, up to the
  37. * current one.
  38. */
  39. private int width;
  40. private int remainingLength;
  41. private int previousRowsLength;
  42. private int totalLength;
  43. private int includedLength;
  44. private int borderBefore;
  45. private int borderAfter;
  46. private int paddingBefore;
  47. private int paddingAfter;
  48. private boolean keepWithNextSignal;
  49. private int lastPenaltyLength;
  50. ActiveCell(PrimaryGridUnit pgu, EffRow row, int rowIndex, int previousRowsLength, TableLayoutManager tableLM) {
  51. this.pgu = pgu;
  52. boolean makeBoxForWholeRow = false;
  53. if (row.getExplicitHeight().min > 0) {
  54. boolean contentsSmaller = ElementListUtils.removeLegalBreaks(
  55. pgu.getElements(), row.getExplicitHeight());
  56. if (contentsSmaller) {
  57. makeBoxForWholeRow = true;
  58. }
  59. }
  60. if (pgu.isLastGridUnitRowSpan() && pgu.getRow() != null) {
  61. makeBoxForWholeRow |= pgu.getRow().mustKeepTogether();
  62. makeBoxForWholeRow |= pgu.getTable().mustKeepTogether();
  63. }
  64. if (makeBoxForWholeRow) {
  65. elementList = new java.util.ArrayList(1);
  66. int height = row.getExplicitHeight().opt;
  67. if (height == 0) {
  68. height = row.getHeight().opt;
  69. }
  70. elementList.add(new KnuthBoxCellWithBPD(height));
  71. } else {
  72. elementList = pgu.getElements();
  73. // if (log.isTraceEnabled()) {
  74. // log.trace("column " + (column+1) + ": recording " + elementLists.size() + " element(s)");
  75. // }
  76. }
  77. includedLength = -1; // Avoid troubles with cells having content of zero length
  78. this.previousRowsLength = previousRowsLength;
  79. width = previousRowsLength;
  80. totalLength = ElementListUtils.calcContentLength(elementList);
  81. if (pgu.getTable().isSeparateBorderModel()) {
  82. borderBefore = pgu.getBorders().getBorderBeforeWidth(false)
  83. + tableLM.getHalfBorderSeparationBPD();
  84. borderAfter = pgu.getBorders().getBorderAfterWidth(false)
  85. + tableLM.getHalfBorderSeparationBPD();
  86. } else {
  87. borderBefore = pgu.getHalfMaxBeforeBorderWidth();
  88. borderAfter = pgu.getHalfMaxAfterBorderWidth();
  89. }
  90. paddingBefore = pgu.getBorders().getPaddingBefore(false, pgu.getCellLM());
  91. paddingAfter = pgu.getBorders().getPaddingAfter(false, pgu.getCellLM());
  92. start = 0;
  93. end = -1;
  94. endRow = rowIndex + pgu.getCell().getNumberRowsSpanned() - 1;
  95. keepWithNextSignal = false;
  96. remainingLength = totalLength;
  97. goToNextLegalBreak();
  98. }
  99. boolean endsOnRow(int rowIndex) {
  100. return rowIndex == endRow;
  101. }
  102. int getRemainingHeight(int activeRowIndex, EffRow[] rowGroup) {
  103. if (!endsOnRow(activeRowIndex)) {
  104. return 0;
  105. } else if (includedLength == totalLength) {
  106. return 0;
  107. } else {
  108. return remainingLength + borderBefore + borderAfter + paddingBefore + paddingAfter;
  109. }
  110. }
  111. private void goToNextLegalBreak() {
  112. lastPenaltyLength = 0;
  113. boolean breakFound = false;
  114. while (!breakFound && end + 1 < elementList.size()) {
  115. end++;
  116. KnuthElement el = (KnuthElement)elementList.get(end);
  117. if (el.isPenalty()) {
  118. prevIsBox = false;
  119. if (el.getP() < KnuthElement.INFINITE) {
  120. //First legal break point
  121. lastPenaltyLength = el.getW();
  122. breakFound = true;
  123. }
  124. } else if (el.isGlue()) {
  125. if (prevIsBox) {
  126. //Second legal break point
  127. breakFound = true;
  128. } else {
  129. width += el.getW();
  130. }
  131. prevIsBox = false;
  132. } else {
  133. prevIsBox = true;
  134. width += el.getW();
  135. }
  136. }
  137. }
  138. int getNextStep() {
  139. if (!includedInLastStep()) {
  140. return width + lastPenaltyLength + borderBefore + borderAfter + paddingBefore + paddingAfter;
  141. } else {
  142. start = end + 1;
  143. if (end < elementList.size() - 1) {
  144. goToNextLegalBreak();
  145. return width + lastPenaltyLength + borderBefore + borderAfter + paddingBefore + paddingAfter;
  146. } else {
  147. return 0;
  148. }
  149. }
  150. }
  151. private boolean includedInLastStep() {
  152. return includedLength == width;
  153. }
  154. boolean signalMinStep(int minStep) {
  155. if (width + lastPenaltyLength + borderBefore + borderAfter + paddingBefore + paddingAfter <= minStep) {
  156. includedLength = width;
  157. computeRemainingLength();
  158. return false;
  159. } else {
  160. return previousRowsLength + borderBefore + borderAfter + paddingBefore + paddingAfter > minStep;
  161. }
  162. }
  163. private void computeRemainingLength() {
  164. remainingLength = totalLength - width;
  165. int index = end + 1;
  166. while (index < elementList.size()) {
  167. KnuthElement el = (KnuthElement)elementList.get(index);
  168. if (el.isBox()) {
  169. break;
  170. } else if (el.isGlue()) {
  171. remainingLength -= el.getW();
  172. }
  173. index++;
  174. }
  175. }
  176. boolean contributesContent() {
  177. return includedInLastStep() && end >= start;
  178. }
  179. boolean hasStarted() {
  180. return includedLength > 0;
  181. }
  182. boolean isFinished() {
  183. return includedInLastStep() && (end == elementList.size() - 1);
  184. }
  185. GridUnitPart createGridUnitPart() {
  186. if (end + 1 == elementList.size()) {
  187. if (pgu.getFlag(GridUnit.KEEP_WITH_NEXT_PENDING)) {
  188. keepWithNextSignal = true;
  189. }
  190. if (pgu.getRow() != null && pgu.getRow().mustKeepWithNext()) {
  191. keepWithNextSignal = true;
  192. }
  193. }
  194. if (start == 0 && end == 0
  195. && elementList.size() == 1
  196. && elementList.get(0) instanceof KnuthBoxCellWithBPD) {
  197. //Special case: Cell with fixed BPD
  198. return new GridUnitPart(pgu, 0, pgu.getElements().size() - 1);
  199. } else {
  200. return new GridUnitPart(pgu, start, end);
  201. }
  202. }
  203. boolean isLastForcedBreak() {
  204. return ((KnuthElement)elementList.get(end)).isForcedBreak();
  205. }
  206. int getLastBreakClass() {
  207. return ((KnuthPenalty)elementList.get(end)).getBreakClass();
  208. }
  209. boolean keepWithNextSignal() {
  210. return keepWithNextSignal;
  211. }
  212. /**
  213. * Marker class denoting table cells fitting in just one box (no legal break inside).
  214. */
  215. private static class KnuthBoxCellWithBPD extends KnuthBox {
  216. public KnuthBoxCellWithBPD(int w) {
  217. super(w, null, true);
  218. }
  219. }
  220. }