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.

ListItemLayoutManager.java 27KB

Merged revisions 636407-637074,637076-637118,637120-637790,637792-637856,637858-637992,637994-638047,638049-638307,638309-638315,638318-638936,638938-640888,640890-642905,642907-647402,647404-647536,647538-648983,648985-649005,649007-649013,649015-650549,650551-651301,651303-653536,653538-654452,654454-656285,656287-656523,656525-657519,657521-661579,661581-663481,663483-664691,664693-681285,681287-681290,681292-681298 via svnmerge from https://svn.apache.org/repos/asf/xmlgraphics/fop/branches/fop-0_95 ........ r666635 | jeremias | 2008-06-11 14:18:53 +0200 (Mi, 11 Jun 2008) | 1 line Fixed resolution handling inside AWT preview dialog. ........ r666662 | jeremias | 2008-06-11 15:33:20 +0200 (Mi, 11 Jun 2008) | 1 line Some notes on RTF and print output. ........ r668533 | jeremias | 2008-06-17 09:57:55 +0200 (Di, 17 Jun 2008) | 2 lines Bugzilla #45151: Note on the "compiling" page that Ant 1.7 is required. The README file already points to this page. ........ r668534 | jeremias | 2008-06-17 09:58:40 +0200 (Di, 17 Jun 2008) | 2 lines Update known issues. Remove ApacheConEU logo. ........ r668550 | jeremias | 2008-06-17 10:05:22 +0200 (Di, 17 Jun 2008) | 2 lines Bugzilla #45146: Removed duplicate LICENSE.txt and Notice.txt from the JAR. ........ r668570 | jeremias | 2008-06-17 10:54:07 +0200 (Di, 17 Jun 2008) | 1 line Wrong line number reported in the case of a line overflow. ........ r668641 | jeremias | 2008-06-17 14:59:25 +0200 (Di, 17 Jun 2008) | 1 line Fixed potential NPE. ........ r669118 | jeremias | 2008-06-18 11:02:45 +0200 (Mi, 18 Jun 2008) | 4 lines Bugzilla #44412: Regression fix for empty pages caused by multiple collapsible breaks. No more empty block areas if a break-before occurs on the first child of an FO to match the behaviour of tables and other FO implementations (clarification by XSL WG pending). Added an accessor interface for break-before/-after to avoid long if..else lists in BlockStackingLayoutManager. ........ r669173 | jeremias | 2008-06-18 16:07:27 +0200 (Mi, 18 Jun 2008) | 7 lines Bugzilla #44887: Fixed potential multi-threading problem concerning the use of DecimalFormat. Results from performance measurements in a separate test (operation repeated 100'000 times, exemplary): shared static variable: ~220ms (old choice, problematic!) always create new instance: ~480ms ThreadLocal: ~220ms (new choice) ........ r669478 | jeremias | 2008-06-19 15:03:57 +0200 (Do, 19 Jun 2008) | 4 lines Bugzilla #44412: Improvements after Vincent's feedback: Removal of the somewhat ugly Reference. getBreakBefore() reduced to private visibility. ........ r670551 | jeremias | 2008-06-23 14:54:27 +0200 (Mo, 23 Jun 2008) | 3 lines Use configured source and target resolution for foreign objects in RTF output. Fixed intrinsic size calculation for SVG images when source resolution is not 72 dpi. Fixed calculation of px2mm values in the SVG to G2D converter (used by RTF output). ........ r673750 | adelmelle | 2008-07-03 20:25:01 +0200 (Do, 03 Jul 2008) | 1 line Fix for Bugzilla 45295 (already committed to the trunk with r672010, r672495 and r672496) ........ r674304 | jeremias | 2008-07-06 17:09:10 +0200 (So, 06 Jul 2008) | 18 lines Bugzilla #43606: column-width accepts percent values (proportional-column-width and % working) Table width accepts percent values (100% of the page width as standard) Nested tables are working It is also possible to make nested tables with a higher depth than 3 without causing word to crash Submitted by: Maximilan Aster <maximilian.aster.at.boc-eu.com> Changes to the patch by Jeremias: - Patch simplified (reuse of ColumnSetup from the layoutmgr package) - Percentages and proportional-column-width didn't work properly in my tests -> fixed - Adjustments for FOP code conventions Bugzilla #43824: page-number-citation working but has to be refreshed inside word to show the correct values Submitted by: Maximilan Aster <maximilian.aster.at.boc-eu.com> Changes to the patch by Jeremias: - Adjustments for FOP code conventions ........ r674314 | jeremias | 2008-07-06 18:40:08 +0200 (So, 06 Jul 2008) | 7 lines Bugzilla #43825: leader supports fixed percent values for leader-length, most other properties use-content, leader-pattern-width not implemented Submitted by: Maximilan Aster <maximilian.aster.at.boc-eu.com> Changes to the patch by Jeremias: - Adjustments for FOP code conventions ........ r674317 | jeremias | 2008-07-06 18:44:43 +0200 (So, 06 Jul 2008) | 1 line Doc update after RTF changes. ........ r675106 | jeremias | 2008-07-09 09:03:46 +0200 (Mi, 09 Jul 2008) | 2 lines Bugzilla #45366: Document missing feature. ........ r675150 | jeremias | 2008-07-09 14:56:41 +0200 (Mi, 09 Jul 2008) | 2 lines Bugzilla #39980: Fixed image scaling for RTF output. ........ r675151 | jeremias | 2008-07-09 14:57:06 +0200 (Mi, 09 Jul 2008) | 1 line Removed unused code. ........ r675152 | jeremias | 2008-07-09 14:58:18 +0200 (Mi, 09 Jul 2008) | 1 line Don't generate commands for default values. ........ r675707 | jeremias | 2008-07-10 21:58:27 +0200 (Do, 10 Jul 2008) | 1 line Bugfix: -imagein didn't work because the stylesheet didn't get copied into fop.jar. ........ r680715 | jeremias | 2008-07-29 16:37:10 +0200 (Di, 29 Jul 2008) | 1 line Found a surplus "pop state" which somehow causes a regression (fill color doesn't get properly reset) between 0.94 and 0.95. Shows in Barcode4J's fop-extension-demo.fo. The line has already been there in 0.94 but only shows in 0.95 probably due to an additional save/restore state pair added in PDFRenderer for reference areas after the block-container area refactoring. ........ r680820 | jeremias | 2008-07-29 22:02:14 +0200 (Di, 29 Jul 2008) | 2 lines Bugzilla #41306: The AWT Renderer is really not out-of-order capable. ........ r681284 | jeremias | 2008-07-31 08:47:49 +0200 (Do, 31 Jul 2008) | 1 line Some updates to status.xml (I was not the only one working on the final release). ........ r681290 | jeremias | 2008-07-31 09:44:51 +0200 (Do, 31 Jul 2008) | 2 lines Website updates for the 0.95 release. The projectInfo plug-in of Forrest is not ideal for doing a bugfix release. It's not possible to combine the changes for two releases. ........ r681292 | jeremias | 2008-07-31 09:47:13 +0200 (Do, 31 Jul 2008) | 1 line Disabling the ApacheCon ad for the release build. ........ git-svn-id: https://svn.apache.org/repos/asf/xmlgraphics/fop/trunk@681307 13f79535-47bb-0310-9956-ffa450edef68
16 년 전
123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714
  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.list;
  19. import java.util.ArrayList;
  20. import java.util.LinkedList;
  21. import java.util.List;
  22. import java.util.ListIterator;
  23. import org.apache.commons.logging.Log;
  24. import org.apache.commons.logging.LogFactory;
  25. import org.apache.fop.area.Area;
  26. import org.apache.fop.area.Block;
  27. import org.apache.fop.fo.flow.ListItem;
  28. import org.apache.fop.fo.flow.ListItemBody;
  29. import org.apache.fop.fo.flow.ListItemLabel;
  30. import org.apache.fop.layoutmgr.BlockLevelLayoutManager;
  31. import org.apache.fop.layoutmgr.BlockStackingLayoutManager;
  32. import org.apache.fop.layoutmgr.BreakElement;
  33. import org.apache.fop.layoutmgr.ConditionalElementListener;
  34. import org.apache.fop.layoutmgr.ElementListObserver;
  35. import org.apache.fop.layoutmgr.ElementListUtils;
  36. import org.apache.fop.layoutmgr.KeepUtil;
  37. import org.apache.fop.layoutmgr.KnuthBlockBox;
  38. import org.apache.fop.layoutmgr.KnuthBox;
  39. import org.apache.fop.layoutmgr.KnuthElement;
  40. import org.apache.fop.layoutmgr.KnuthPenalty;
  41. import org.apache.fop.layoutmgr.KnuthPossPosIter;
  42. import org.apache.fop.layoutmgr.LayoutContext;
  43. import org.apache.fop.layoutmgr.LayoutManager;
  44. import org.apache.fop.layoutmgr.ListElement;
  45. import org.apache.fop.layoutmgr.NonLeafPosition;
  46. import org.apache.fop.layoutmgr.Position;
  47. import org.apache.fop.layoutmgr.PositionIterator;
  48. import org.apache.fop.layoutmgr.RelSide;
  49. import org.apache.fop.layoutmgr.SpaceResolver;
  50. import org.apache.fop.layoutmgr.TraitSetter;
  51. import org.apache.fop.traits.MinOptMax;
  52. import org.apache.fop.traits.SpaceVal;
  53. /**
  54. * LayoutManager for a list-item FO.
  55. * The list item contains a list item label and a list item body.
  56. */
  57. public class ListItemLayoutManager extends BlockStackingLayoutManager
  58. implements ConditionalElementListener {
  59. /**
  60. * logging instance
  61. */
  62. private static Log log = LogFactory.getLog(ListItemLayoutManager.class);
  63. private ListItemContentLayoutManager label;
  64. private ListItemContentLayoutManager body;
  65. private Block curBlockArea = null;
  66. private List labelList = null;
  67. private List bodyList = null;
  68. private boolean discardBorderBefore;
  69. private boolean discardBorderAfter;
  70. private boolean discardPaddingBefore;
  71. private boolean discardPaddingAfter;
  72. private MinOptMax effSpaceBefore;
  73. private MinOptMax effSpaceAfter;
  74. private int keepWithNextPendingOnLabel;
  75. private int keepWithNextPendingOnBody;
  76. private int listItemHeight;
  77. private class ListItemPosition extends Position {
  78. private int iLabelFirstIndex;
  79. private int iLabelLastIndex;
  80. private int iBodyFirstIndex;
  81. private int iBodyLastIndex;
  82. public ListItemPosition(LayoutManager lm, int labelFirst, int labelLast,
  83. int bodyFirst, int bodyLast) {
  84. super(lm);
  85. iLabelFirstIndex = labelFirst;
  86. iLabelLastIndex = labelLast;
  87. iBodyFirstIndex = bodyFirst;
  88. iBodyLastIndex = bodyLast;
  89. }
  90. public int getLabelFirstIndex() {
  91. return iLabelFirstIndex;
  92. }
  93. public int getLabelLastIndex() {
  94. return iLabelLastIndex;
  95. }
  96. public int getBodyFirstIndex() {
  97. return iBodyFirstIndex;
  98. }
  99. public int getBodyLastIndex() {
  100. return iBodyLastIndex;
  101. }
  102. /** {@inheritDoc} */
  103. public boolean generatesAreas() {
  104. return true;
  105. }
  106. /** {@inheritDoc} */
  107. public String toString() {
  108. StringBuffer sb = new StringBuffer("ListItemPosition:");
  109. sb.append(getIndex()).append("(");
  110. sb.append("label:").append(iLabelFirstIndex).append("-").append(iLabelLastIndex);
  111. sb.append(" body:").append(iBodyFirstIndex).append("-").append(iBodyLastIndex);
  112. sb.append(")");
  113. return sb.toString();
  114. }
  115. }
  116. /**
  117. * Create a new list item layout manager.
  118. * @param node list-item to create the layout manager for
  119. */
  120. public ListItemLayoutManager(ListItem node) {
  121. super(node);
  122. setLabel(node.getLabel());
  123. setBody(node.getBody());
  124. }
  125. /**
  126. * Convenience method.
  127. * @return the ListBlock node
  128. */
  129. protected ListItem getListItemFO() {
  130. return (ListItem)fobj;
  131. }
  132. /**
  133. * Create a LM for the fo:list-item-label object
  134. * @param node the fo:list-item-label FO
  135. */
  136. public void setLabel(ListItemLabel node) {
  137. label = new ListItemContentLayoutManager(node);
  138. label.setParent(this);
  139. }
  140. /**
  141. * Create a LM for the fo:list-item-body object
  142. * @param node the fo:list-item-body FO
  143. */
  144. public void setBody(ListItemBody node) {
  145. body = new ListItemContentLayoutManager(node);
  146. body.setParent(this);
  147. }
  148. /** {@inheritDoc} */
  149. public void initialize() {
  150. foSpaceBefore = new SpaceVal(
  151. getListItemFO().getCommonMarginBlock().spaceBefore, this).getSpace();
  152. foSpaceAfter = new SpaceVal(
  153. getListItemFO().getCommonMarginBlock().spaceAfter, this).getSpace();
  154. startIndent = getListItemFO().getCommonMarginBlock().startIndent.getValue(this);
  155. endIndent = getListItemFO().getCommonMarginBlock().endIndent.getValue(this);
  156. }
  157. private void resetSpaces() {
  158. this.discardBorderBefore = false;
  159. this.discardBorderAfter = false;
  160. this.discardPaddingBefore = false;
  161. this.discardPaddingAfter = false;
  162. this.effSpaceBefore = null;
  163. this.effSpaceAfter = null;
  164. }
  165. /** {@inheritDoc} */
  166. public List getNextKnuthElements(LayoutContext context, int alignment) {
  167. referenceIPD = context.getRefIPD();
  168. LayoutContext childLC;
  169. List returnList = new LinkedList();
  170. if (!breakBeforeServed) {
  171. breakBeforeServed = true;
  172. if (!context.suppressBreakBefore()) {
  173. if (addKnuthElementsForBreakBefore(returnList, context)) {
  174. return returnList;
  175. }
  176. }
  177. }
  178. addKnuthElementsForSpaceBefore(returnList, alignment);
  179. addKnuthElementsForBorderPaddingBefore(returnList, !firstVisibleMarkServed);
  180. firstVisibleMarkServed = true;
  181. //Spaces, border and padding to be repeated at each break
  182. addPendingMarks(context);
  183. // label
  184. childLC = new LayoutContext(0);
  185. childLC.setRefIPD(context.getRefIPD());
  186. label.initialize();
  187. labelList = label.getNextKnuthElements(childLC, alignment);
  188. //Space resolution as if the contents were placed in a new reference area
  189. //(see 6.8.3, XSL 1.0, section on Constraints, last paragraph)
  190. SpaceResolver.resolveElementList(labelList);
  191. ElementListObserver.observe(labelList, "list-item-label", label.getPartFO().getId());
  192. context.updateKeepWithPreviousPending(childLC.getKeepWithPreviousPending());
  193. this.keepWithNextPendingOnLabel = childLC.getKeepWithNextPending();
  194. // body
  195. childLC = new LayoutContext(0);
  196. childLC.setRefIPD(context.getRefIPD());
  197. body.initialize();
  198. bodyList = body.getNextKnuthElements(childLC, alignment);
  199. //Space resolution as if the contents were placed in a new reference area
  200. //(see 6.8.3, XSL 1.0, section on Constraints, last paragraph)
  201. SpaceResolver.resolveElementList(bodyList);
  202. ElementListObserver.observe(bodyList, "list-item-body", body.getPartFO().getId());
  203. context.updateKeepWithPreviousPending(childLC.getKeepWithPreviousPending());
  204. this.keepWithNextPendingOnBody = childLC.getKeepWithNextPending();
  205. // create a combined list
  206. List returnedList = getCombinedKnuthElementsForListItem(labelList, bodyList, context);
  207. // "wrap" the Position inside each element
  208. wrapPositionElements(returnedList, returnList, true);
  209. addKnuthElementsForBorderPaddingAfter(returnList, true);
  210. addKnuthElementsForSpaceAfter(returnList, alignment);
  211. addKnuthElementsForBreakAfter(returnList, context);
  212. context.updateKeepWithNextPending(this.keepWithNextPendingOnLabel);
  213. context.updateKeepWithNextPending(this.keepWithNextPendingOnBody);
  214. context.updateKeepWithNextPending(getKeepWithNextStrength());
  215. context.updateKeepWithPreviousPending(getKeepWithPreviousStrength());
  216. setFinished(true);
  217. resetSpaces();
  218. return returnList;
  219. }
  220. private List getCombinedKnuthElementsForListItem(List labelElements,
  221. List bodyElements, LayoutContext context) {
  222. // Copy elements to array lists to improve element access performance
  223. List[] elementLists = {new ArrayList(labelElements),
  224. new ArrayList(bodyElements)};
  225. int[] fullHeights = {ElementListUtils.calcContentLength(elementLists[0]),
  226. ElementListUtils.calcContentLength(elementLists[1])};
  227. int[] partialHeights = {0, 0};
  228. int[] start = {-1, -1};
  229. int[] end = {-1, -1};
  230. int totalHeight = Math.max(fullHeights[0], fullHeights[1]);
  231. int step;
  232. int addedBoxHeight = 0;
  233. int keepWithNextActive = BlockLevelLayoutManager.KEEP_AUTO;
  234. LinkedList returnList = new LinkedList();
  235. while ((step = getNextStep(elementLists, start, end, partialHeights)) > 0) {
  236. if (end[0] + 1 == elementLists[0].size()) {
  237. keepWithNextActive = Math.max(keepWithNextActive, keepWithNextPendingOnLabel);
  238. }
  239. if (end[1] + 1 == elementLists[1].size()) {
  240. keepWithNextActive = Math.max(keepWithNextActive, keepWithNextPendingOnBody);
  241. }
  242. // compute penalty height and box height
  243. int penaltyHeight = step
  244. + getMaxRemainingHeight(fullHeights, partialHeights)
  245. - totalHeight;
  246. //Additional penalty height from penalties in the source lists
  247. int additionalPenaltyHeight = 0;
  248. int stepPenalty = 0;
  249. KnuthElement endEl = (KnuthElement)elementLists[0].get(end[0]);
  250. if (endEl instanceof KnuthPenalty) {
  251. additionalPenaltyHeight = endEl.getW();
  252. stepPenalty = Math.max(stepPenalty, endEl.getP());
  253. }
  254. endEl = (KnuthElement)elementLists[1].get(end[1]);
  255. if (endEl instanceof KnuthPenalty) {
  256. additionalPenaltyHeight = Math.max(
  257. additionalPenaltyHeight, endEl.getW());
  258. stepPenalty = Math.max(stepPenalty, endEl.getP());
  259. }
  260. int boxHeight = step - addedBoxHeight - penaltyHeight;
  261. penaltyHeight += additionalPenaltyHeight; //Add AFTER calculating boxHeight!
  262. // collect footnote information
  263. // TODO this should really not be done like this. ListItemLM should remain as
  264. // footnote-agnostic as possible
  265. LinkedList footnoteList = null;
  266. ListElement el;
  267. for (int i = 0; i < elementLists.length; i++) {
  268. for (int j = start[i]; j <= end[i]; j++) {
  269. el = (ListElement) elementLists[i].get(j);
  270. if (el instanceof KnuthBlockBox && ((KnuthBlockBox) el).hasAnchors()) {
  271. if (footnoteList == null) {
  272. footnoteList = new LinkedList();
  273. }
  274. footnoteList.addAll(((KnuthBlockBox) el).getFootnoteBodyLMs());
  275. }
  276. }
  277. }
  278. // add the new elements
  279. addedBoxHeight += boxHeight;
  280. ListItemPosition stepPosition = new ListItemPosition(this,
  281. start[0], end[0], start[1], end[1]);
  282. if (footnoteList == null) {
  283. returnList.add(new KnuthBox(boxHeight, stepPosition, false));
  284. } else {
  285. returnList.add(new KnuthBlockBox(boxHeight, footnoteList, stepPosition, false));
  286. }
  287. if (addedBoxHeight < totalHeight) {
  288. int strength = BlockLevelLayoutManager.KEEP_AUTO;
  289. strength = Math.max(strength, keepWithNextActive);
  290. strength = Math.max(strength, getKeepTogetherStrength());
  291. int p = stepPenalty;
  292. if (p > -KnuthElement.INFINITE) {
  293. p = Math.max(p, KeepUtil.getPenaltyForKeep(strength));
  294. }
  295. returnList.add(new BreakElement(stepPosition, penaltyHeight, p, -1, context));
  296. }
  297. }
  298. return returnList;
  299. }
  300. private int getNextStep(List[] elementLists, int[] start, int[] end, int[] partialHeights) {
  301. // backup of partial heights
  302. int[] backupHeights = {partialHeights[0], partialHeights[1]};
  303. // set starting points
  304. start[0] = end[0] + 1;
  305. start[1] = end[1] + 1;
  306. // get next possible sequence for label and body
  307. int seqCount = 0;
  308. for (int i = 0; i < start.length; i++) {
  309. while (end[i] + 1 < elementLists[i].size()) {
  310. end[i]++;
  311. KnuthElement el = (KnuthElement)elementLists[i].get(end[i]);
  312. if (el.isPenalty()) {
  313. if (el.getP() < KnuthElement.INFINITE) {
  314. //First legal break point
  315. break;
  316. }
  317. } else if (el.isGlue()) {
  318. if (end[i] > 0) {
  319. KnuthElement prev = (KnuthElement)elementLists[i].get(end[i] - 1);
  320. if (prev.isBox()) {
  321. //Second legal break point
  322. break;
  323. }
  324. }
  325. partialHeights[i] += el.getW();
  326. } else {
  327. partialHeights[i] += el.getW();
  328. }
  329. }
  330. if (end[i] < start[i]) {
  331. partialHeights[i] = backupHeights[i];
  332. } else {
  333. seqCount++;
  334. }
  335. }
  336. if (seqCount == 0) {
  337. return 0;
  338. }
  339. // determine next step
  340. int step;
  341. if (backupHeights[0] == 0 && backupHeights[1] == 0) {
  342. // this is the first step: choose the maximum increase, so that
  343. // the smallest area in the first page will contain at least
  344. // a label area and a body area
  345. step = Math.max((end[0] >= start[0] ? partialHeights[0] : Integer.MIN_VALUE),
  346. (end[1] >= start[1] ? partialHeights[1] : Integer.MIN_VALUE));
  347. } else {
  348. // this is not the first step: choose the minimum increase
  349. step = Math.min((end[0] >= start[0] ? partialHeights[0] : Integer.MAX_VALUE),
  350. (end[1] >= start[1] ? partialHeights[1] : Integer.MAX_VALUE));
  351. }
  352. // reset bigger-than-step sequences
  353. for (int i = 0; i < partialHeights.length; i++) {
  354. if (partialHeights[i] > step) {
  355. partialHeights[i] = backupHeights[i];
  356. end[i] = start[i] - 1;
  357. }
  358. }
  359. return step;
  360. }
  361. private int getMaxRemainingHeight(int[] fullHeights, int[] partialHeights) {
  362. return Math.max(fullHeights[0] - partialHeights[0],
  363. fullHeights[1] - partialHeights[1]);
  364. }
  365. /**
  366. * {@inheritDoc}
  367. */
  368. public List getChangedKnuthElements(List oldList, int alignment) {
  369. //log.debug(" LILM.getChanged> label");
  370. // label
  371. labelList = label.getChangedKnuthElements(labelList, alignment);
  372. //log.debug(" LILM.getChanged> body");
  373. // body
  374. // "unwrap" the Positions stored in the elements
  375. ListIterator oldListIterator = oldList.listIterator();
  376. KnuthElement oldElement;
  377. while (oldListIterator.hasNext()) {
  378. oldElement = (KnuthElement)oldListIterator.next();
  379. Position innerPosition = oldElement.getPosition().getPosition();
  380. //log.debug(" BLM> unwrapping: " + (oldElement.isBox()
  381. // ? "box " : (oldElement.isGlue() ? "glue " : "penalty"))
  382. // + " creato da " + oldElement.getLayoutManager().getClass().getName());
  383. //log.debug(" BLM> unwrapping: "
  384. // + oldElement.getPosition().getClass().getName());
  385. if (innerPosition != null) {
  386. // oldElement was created by a descendant of this BlockLM
  387. oldElement.setPosition(innerPosition);
  388. } else {
  389. // thisElement was created by this BlockLM
  390. // modify its position in order to recognize it was not created
  391. // by a child
  392. oldElement.setPosition(new Position(this));
  393. }
  394. }
  395. List returnedList = body.getChangedKnuthElements(oldList, alignment);
  396. // "wrap" the Position inside each element
  397. List tempList = returnedList;
  398. KnuthElement tempElement;
  399. returnedList = new LinkedList();
  400. ListIterator listIter = tempList.listIterator();
  401. while (listIter.hasNext()) {
  402. tempElement = (KnuthElement)listIter.next();
  403. tempElement.setPosition(new NonLeafPosition(this, tempElement.getPosition()));
  404. returnedList.add(tempElement);
  405. }
  406. return returnedList;
  407. }
  408. /**
  409. * Add the areas for the break points.
  410. * This sets the offset of each cell as it is added.
  411. *
  412. * @param parentIter the position iterator
  413. * @param layoutContext the layout context for adding areas
  414. */
  415. public void addAreas(PositionIterator parentIter,
  416. LayoutContext layoutContext) {
  417. getParentArea(null);
  418. addId();
  419. LayoutContext lc = new LayoutContext(0);
  420. Position firstPos = null;
  421. Position lastPos = null;
  422. // "unwrap" the NonLeafPositions stored in parentIter
  423. LinkedList positionList = new LinkedList();
  424. Position pos;
  425. while (parentIter.hasNext()) {
  426. pos = (Position) parentIter.next();
  427. if (pos.getIndex() >= 0) {
  428. if (firstPos == null) {
  429. firstPos = pos;
  430. }
  431. lastPos = pos;
  432. }
  433. if (pos instanceof NonLeafPosition && pos.getPosition() != null) {
  434. // pos contains a ListItemPosition created by this ListBlockLM
  435. positionList.add(pos.getPosition());
  436. }
  437. }
  438. addMarkersToPage(true, isFirst(firstPos), isLast(lastPos));
  439. // use the first and the last ListItemPosition to determine the
  440. // corresponding indexes in the original labelList and bodyList
  441. int labelFirstIndex = ((ListItemPosition) positionList.getFirst()).getLabelFirstIndex();
  442. int labelLastIndex = ((ListItemPosition) positionList.getLast()).getLabelLastIndex();
  443. int bodyFirstIndex = ((ListItemPosition) positionList.getFirst()).getBodyFirstIndex();
  444. int bodyLastIndex = ((ListItemPosition) positionList.getLast()).getBodyLastIndex();
  445. //Determine previous break if any
  446. int previousBreak = ElementListUtils.determinePreviousBreak(labelList, labelFirstIndex);
  447. SpaceResolver.performConditionalsNotification(labelList,
  448. labelFirstIndex, labelLastIndex, previousBreak);
  449. //Determine previous break if any
  450. previousBreak = ElementListUtils.determinePreviousBreak(bodyList, bodyFirstIndex);
  451. SpaceResolver.performConditionalsNotification(bodyList,
  452. bodyFirstIndex, bodyLastIndex, previousBreak);
  453. // add label areas
  454. if (labelFirstIndex <= labelLastIndex) {
  455. KnuthPossPosIter labelIter = new KnuthPossPosIter(labelList,
  456. labelFirstIndex, labelLastIndex + 1);
  457. lc.setFlags(LayoutContext.FIRST_AREA, layoutContext.isFirstArea());
  458. lc.setFlags(LayoutContext.LAST_AREA, layoutContext.isLastArea());
  459. // set the space adjustment ratio
  460. lc.setSpaceAdjust(layoutContext.getSpaceAdjust());
  461. // TO DO: use the right stack limit for the label
  462. lc.setStackLimitBP(layoutContext.getStackLimitBP());
  463. label.addAreas(labelIter, lc);
  464. }
  465. // reset the area bpd after adding the label areas and before adding the body areas
  466. int savedBPD = 0;
  467. if (labelFirstIndex <= labelLastIndex
  468. && bodyFirstIndex <= bodyLastIndex) {
  469. savedBPD = curBlockArea.getBPD();
  470. curBlockArea.setBPD(0);
  471. }
  472. // add body areas
  473. if (bodyFirstIndex <= bodyLastIndex) {
  474. KnuthPossPosIter bodyIter = new KnuthPossPosIter(bodyList,
  475. bodyFirstIndex, bodyLastIndex + 1);
  476. lc.setFlags(LayoutContext.FIRST_AREA, layoutContext.isFirstArea());
  477. lc.setFlags(LayoutContext.LAST_AREA, layoutContext.isLastArea());
  478. // set the space adjustment ratio
  479. lc.setSpaceAdjust(layoutContext.getSpaceAdjust());
  480. // TO DO: use the right stack limit for the body
  481. lc.setStackLimitBP(layoutContext.getStackLimitBP());
  482. body.addAreas(bodyIter, lc);
  483. }
  484. // after adding body areas, set the maximum area bpd
  485. if (curBlockArea.getBPD() < savedBPD) {
  486. curBlockArea.setBPD(savedBPD);
  487. }
  488. addMarkersToPage(false, isFirst(firstPos), isLast(lastPos));
  489. // We are done with this area add the background
  490. TraitSetter.addBackground(curBlockArea,
  491. getListItemFO().getCommonBorderPaddingBackground(),
  492. this);
  493. TraitSetter.addSpaceBeforeAfter(curBlockArea, layoutContext.getSpaceAdjust(),
  494. effSpaceBefore, effSpaceAfter);
  495. flush();
  496. curBlockArea = null;
  497. resetSpaces();
  498. checkEndOfLayout(lastPos);
  499. }
  500. /**
  501. * Get the height of the list item after adjusting.
  502. * Should only be called after adding the list item areas.
  503. *
  504. * @return the height of this list item after adjustment
  505. */
  506. public int getListItemHeight() {
  507. return listItemHeight;
  508. }
  509. /**
  510. * Return an Area which can contain the passed childArea. The childArea
  511. * may not yet have any content, but it has essential traits set.
  512. * In general, if the LayoutManager already has an Area it simply returns
  513. * it. Otherwise, it makes a new Area of the appropriate class.
  514. * It gets a parent area for its area by calling its parent LM.
  515. * Finally, based on the dimensions of the parent area, it initializes
  516. * its own area. This includes setting the content IPD and the maximum
  517. * BPD.
  518. *
  519. * @param childArea the child area
  520. * @return the parent are for the child
  521. */
  522. public Area getParentArea(Area childArea) {
  523. if (curBlockArea == null) {
  524. curBlockArea = new Block();
  525. // Set up dimensions
  526. /*Area parentArea =*/ parentLM.getParentArea(curBlockArea);
  527. // set traits
  528. TraitSetter.setProducerID(curBlockArea, getListItemFO().getId());
  529. TraitSetter.addBorders(curBlockArea,
  530. getListItemFO().getCommonBorderPaddingBackground(),
  531. discardBorderBefore, discardBorderAfter, false, false, this);
  532. TraitSetter.addPadding(curBlockArea,
  533. getListItemFO().getCommonBorderPaddingBackground(),
  534. discardPaddingBefore, discardPaddingAfter, false, false, this);
  535. TraitSetter.addMargins(curBlockArea,
  536. getListItemFO().getCommonBorderPaddingBackground(),
  537. getListItemFO().getCommonMarginBlock(), this);
  538. TraitSetter.addBreaks(curBlockArea,
  539. getListItemFO().getBreakBefore(),
  540. getListItemFO().getBreakAfter());
  541. int contentIPD = referenceIPD - getIPIndents();
  542. curBlockArea.setIPD(contentIPD);
  543. setCurrentArea(curBlockArea);
  544. }
  545. return curBlockArea;
  546. }
  547. /**
  548. * Add the child.
  549. * Rows return the areas returned by the child elements.
  550. * This simply adds the area to the parent layout manager.
  551. *
  552. * @param childArea the child area
  553. */
  554. public void addChildArea(Area childArea) {
  555. if (curBlockArea != null) {
  556. curBlockArea.addBlock((Block) childArea);
  557. }
  558. }
  559. /** {@inheritDoc} */
  560. public int getKeepTogetherStrength() {
  561. int strength = KeepUtil.getCombinedBlockLevelKeepStrength(
  562. getListItemFO().getKeepTogether());
  563. strength = Math.max(strength, getParentKeepTogetherStrength());
  564. return strength;
  565. }
  566. /** {@inheritDoc} */
  567. public int getKeepWithNextStrength() {
  568. return KeepUtil.getCombinedBlockLevelKeepStrength(getListItemFO().getKeepWithNext());
  569. }
  570. /** {@inheritDoc} */
  571. public int getKeepWithPreviousStrength() {
  572. return KeepUtil.getCombinedBlockLevelKeepStrength(getListItemFO().getKeepWithPrevious());
  573. }
  574. /** {@inheritDoc} */
  575. public void notifySpace(RelSide side, MinOptMax effectiveLength) {
  576. if (RelSide.BEFORE == side) {
  577. if (log.isDebugEnabled()) {
  578. log.debug(this + ": Space " + side + ", "
  579. + this.effSpaceBefore + "-> " + effectiveLength);
  580. }
  581. this.effSpaceBefore = effectiveLength;
  582. } else {
  583. if (log.isDebugEnabled()) {
  584. log.debug(this + ": Space " + side + ", "
  585. + this.effSpaceAfter + "-> " + effectiveLength);
  586. }
  587. this.effSpaceAfter = effectiveLength;
  588. }
  589. }
  590. /** {@inheritDoc} */
  591. public void notifyBorder(RelSide side, MinOptMax effectiveLength) {
  592. if (effectiveLength == null) {
  593. if (RelSide.BEFORE == side) {
  594. this.discardBorderBefore = true;
  595. } else {
  596. this.discardBorderAfter = true;
  597. }
  598. }
  599. if (log.isDebugEnabled()) {
  600. log.debug(this + ": Border " + side + " -> " + effectiveLength);
  601. }
  602. }
  603. /** {@inheritDoc} */
  604. public void notifyPadding(RelSide side, MinOptMax effectiveLength) {
  605. if (effectiveLength == null) {
  606. if (RelSide.BEFORE == side) {
  607. this.discardPaddingBefore = true;
  608. } else {
  609. this.discardPaddingAfter = true;
  610. }
  611. }
  612. if (log.isDebugEnabled()) {
  613. log.debug(this + ": Padding " + side + " -> " + effectiveLength);
  614. }
  615. }
  616. }