您最多选择25个主题 主题必须以字母或数字开头,可以包含连字符 (-),并且长度不得超过35个字符

FootnoteLayoutManager.java 7.8KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200
  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.inline;
  19. import java.util.LinkedList;
  20. import java.util.List;
  21. import java.util.ListIterator;
  22. import org.apache.commons.logging.Log;
  23. import org.apache.commons.logging.LogFactory;
  24. import org.apache.fop.fo.flow.Footnote;
  25. import org.apache.fop.layoutmgr.FootnoteBodyLayoutManager;
  26. import org.apache.fop.layoutmgr.InlineKnuthSequence;
  27. import org.apache.fop.layoutmgr.KnuthElement;
  28. import org.apache.fop.layoutmgr.KnuthSequence;
  29. import org.apache.fop.layoutmgr.LayoutContext;
  30. import org.apache.fop.layoutmgr.LayoutManager;
  31. import org.apache.fop.layoutmgr.ListElement;
  32. import org.apache.fop.layoutmgr.NonLeafPosition;
  33. import org.apache.fop.layoutmgr.Position;
  34. import org.apache.fop.layoutmgr.PositionIterator;
  35. /**
  36. * Layout manager for fo:footnote.
  37. */
  38. public class FootnoteLayoutManager extends InlineStackingLayoutManager {
  39. /**
  40. * logging instance
  41. */
  42. private static Log log = LogFactory.getLog(FootnoteLayoutManager.class);
  43. private Footnote footnote;
  44. private InlineStackingLayoutManager citationLM;
  45. private FootnoteBodyLayoutManager bodyLM;
  46. /** Represents the footnote citation **/
  47. private KnuthElement forcedAnchor;
  48. /**
  49. * Create a new footnote layout manager.
  50. * @param node footnote to create the layout manager for
  51. */
  52. public FootnoteLayoutManager(Footnote node) {
  53. super(node);
  54. footnote = node;
  55. }
  56. /** {@inheritDoc} */
  57. @Override
  58. public void initialize() {
  59. // create an InlineStackingLM handling the fo:inline child of fo:footnote
  60. citationLM = new InlineLayoutManager(footnote.getFootnoteCitation());
  61. // create a FootnoteBodyLM handling the fo:footnote-body child of fo:footnote
  62. bodyLM = new FootnoteBodyLayoutManager(footnote.getFootnoteBody());
  63. }
  64. /** {@inheritDoc} */
  65. @Override
  66. public List getNextKnuthElements(LayoutContext context,
  67. int alignment) {
  68. // for the moment, this LM is set as the citationLM's parent
  69. // later on, when this LM will have nothing more to do, the citationLM's parent
  70. // will be set to the fotnoteLM's parent
  71. citationLM.setParent(this);
  72. citationLM.initialize();
  73. bodyLM.setParent(this);
  74. bodyLM.initialize();
  75. // get Knuth elements representing the footnote citation
  76. List returnedList = new LinkedList();
  77. while (!citationLM.isFinished()) {
  78. List partialList = citationLM.getNextKnuthElements(context, alignment);
  79. if (partialList != null) {
  80. returnedList.addAll(partialList);
  81. }
  82. }
  83. if (returnedList.size() == 0) {
  84. //Inline part of the footnote is empty. Need to send back an auxiliary
  85. //zero-width, zero-height inline box so the footnote gets painted.
  86. KnuthSequence seq = new InlineKnuthSequence();
  87. //Need to use an aux. box, otherwise, the line height can't be forced to zero height.
  88. forcedAnchor = new KnuthInlineBox(0, null, null, true);
  89. seq.add(forcedAnchor);
  90. returnedList.add(seq);
  91. }
  92. setFinished(true);
  93. addAnchor(returnedList);
  94. // "wrap" the Position stored in each list inside returnedList
  95. ListIterator listIterator = returnedList.listIterator();
  96. ListIterator elementIterator = null;
  97. KnuthSequence list = null;
  98. ListElement element = null;
  99. while (listIterator.hasNext()) {
  100. list = (KnuthSequence) listIterator.next();
  101. elementIterator = list.listIterator();
  102. while (elementIterator.hasNext()) {
  103. element = (KnuthElement) elementIterator.next();
  104. element.setPosition(notifyPos(new NonLeafPosition(this, element.getPosition())));
  105. }
  106. }
  107. return returnedList;
  108. }
  109. /** {@inheritDoc} */
  110. @Override
  111. public List getChangedKnuthElements(List oldList, int alignment, int depth) {
  112. List returnedList = super.getChangedKnuthElements(oldList, alignment, depth);
  113. addAnchor(returnedList);
  114. return returnedList;
  115. }
  116. /** {@inheritDoc} */
  117. @Override
  118. public void addAreas(PositionIterator posIter, LayoutContext context) {
  119. // "Unwrap" the NonLeafPositions stored in posIter and put
  120. // them in a new list, that will be given to the citationLM
  121. LinkedList<Position> positionList = new LinkedList<Position>();
  122. Position pos;
  123. while (posIter.hasNext()) {
  124. pos = posIter.next();
  125. if (pos != null && pos.getPosition() != null) {
  126. positionList.add(pos.getPosition());
  127. }
  128. }
  129. // FootnoteLM does not create any area,
  130. // so the citationLM child will add directly to the FootnoteLM parent area
  131. citationLM.setParent(getParent());
  132. // make the citationLM add its areas
  133. LayoutContext childContext = LayoutContext.copyOf(context);
  134. PositionIterator childPosIter = new PositionIterator(positionList.listIterator());
  135. LayoutManager childLM;
  136. while ((childLM = childPosIter.getNextChildLM()) != null) {
  137. childLM.setFromFootnote(true);
  138. childLM.addAreas(childPosIter, childContext);
  139. childContext.setLeadingSpace(childContext.getTrailingSpace());
  140. childContext.setFlags(LayoutContext.RESOLVE_LEADING_SPACE, true);
  141. }
  142. }
  143. /**
  144. * Find the last box in the sequence, and add a reference to the FootnoteBodyLM
  145. * @param citationList the list of elements representing the footnote citation
  146. */
  147. private void addAnchor(List citationList) {
  148. KnuthInlineBox lastBox = null;
  149. // the list of elements is searched backwards, until we find a box
  150. ListIterator citationIterator = citationList.listIterator(citationList.size());
  151. while (citationIterator.hasPrevious() && lastBox == null) {
  152. Object obj = citationIterator.previous();
  153. if (obj instanceof KnuthElement) {
  154. // obj is an element
  155. KnuthElement element = (KnuthElement)obj;
  156. if (element instanceof KnuthInlineBox) {
  157. lastBox = (KnuthInlineBox) element;
  158. }
  159. } else {
  160. // obj is a sequence of elements
  161. KnuthSequence seq = (KnuthSequence)obj;
  162. ListIterator nestedIterator = seq.listIterator(seq.size());
  163. while (nestedIterator.hasPrevious() && lastBox == null) {
  164. KnuthElement element = (KnuthElement)nestedIterator.previous();
  165. if (element instanceof KnuthInlineBox && !element.isAuxiliary()
  166. || element == forcedAnchor) {
  167. lastBox = (KnuthInlineBox) element;
  168. }
  169. }
  170. }
  171. }
  172. if (lastBox != null) {
  173. lastBox.setFootnoteBodyLM(bodyLM);
  174. } else {
  175. //throw new IllegalStateException("No anchor box was found for a footnote.");
  176. }
  177. }
  178. }