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 18 /* $Id$ */ 19 20 package org.apache.fop.layoutmgr; 21 22 import java.util.LinkedList; 23 import java.util.List; 24 25 import org.apache.fop.fo.FObj; 26 import org.apache.fop.layoutmgr.PageBreakingAlgorithm.PageBreakingLayoutListener; 27 import org.apache.fop.layoutmgr.inline.TextLayoutManager; 28 29 public abstract class LocalBreaker extends AbstractBreaker { 30 protected BlockStackingLayoutManager lm; 31 private int displayAlign; 32 private int ipd; 33 private int overflow; 34 private boolean repeatedHeader; 35 private boolean isDescendantOfTableFooter; 36 private boolean repeatedFooter; 37 setRepeatedFooter(boolean repeatedFooter)38 public void setRepeatedFooter(boolean repeatedFooter) { 39 this.repeatedFooter = repeatedFooter; 40 } 41 setDescendantOfTableFooter(boolean isDescendantOfTableFooter)42 public void setDescendantOfTableFooter(boolean isDescendantOfTableFooter) { 43 this.isDescendantOfTableFooter = isDescendantOfTableFooter; 44 } 45 LocalBreaker(BlockStackingLayoutManager lm, int ipd, int displayAlign)46 public LocalBreaker(BlockStackingLayoutManager lm, int ipd, int displayAlign) { 47 this.lm = lm; 48 this.ipd = ipd; 49 this.displayAlign = displayAlign; 50 } 51 setRepeatedHeader(boolean repeatedHeader)52 public void setRepeatedHeader(boolean repeatedHeader) { 53 this.repeatedHeader = repeatedHeader; 54 } 55 56 /** {@inheritDoc} */ isPartOverflowRecoveryActivated()57 protected boolean isPartOverflowRecoveryActivated() { 58 // For side regions, this must be disabled because of wanted overflow. 59 return false; 60 } 61 isOverflow()62 public boolean isOverflow() { 63 return (this.overflow != 0); 64 } 65 getOverflowAmount()66 public int getOverflowAmount() { 67 return this.overflow; 68 } 69 70 /** {@inheritDoc} */ createLayoutListener()71 protected PageBreakingLayoutListener createLayoutListener() { 72 return new PageBreakingLayoutListener() { 73 74 public void notifyOverflow(int part, int amount, FObj obj) { 75 if (LocalBreaker.this.overflow == 0) { 76 LocalBreaker.this.overflow = amount; 77 } 78 } 79 80 }; 81 } 82 83 protected LayoutManager getTopLevelLM() { 84 return lm; 85 } 86 87 protected LayoutContext createLayoutContext() { 88 LayoutContext lc = super.createLayoutContext(); 89 lc.setRefIPD(ipd); 90 return lc; 91 } 92 93 protected List getNextKnuthElements(LayoutContext context, int alignment) { 94 LayoutManager curLM; // currently active LM 95 List returnList = new LinkedList(); 96 97 while ((curLM = lm.getChildLM()) != null) { 98 LayoutContext childLC = LayoutContext.newInstance(); 99 childLC.setStackLimitBP(context.getStackLimitBP()); 100 childLC.setRefIPD(context.getRefIPD()); 101 childLC.setWritingMode(context.getWritingMode()); 102 103 List returnedList = null; 104 // The following is a HACK! Ignore leading and trailing white space 105 boolean ignore = curLM instanceof TextLayoutManager; 106 if (!curLM.isFinished()) { 107 returnedList = curLM.getNextKnuthElements(childLC, alignment); 108 } 109 if (returnedList != null && !ignore) { 110 lm.wrapPositionElements(returnedList, returnList); 111 } 112 } 113 SpaceResolver.resolveElementList(returnList); 114 lm.setFinished(true); 115 return returnList; 116 } 117 118 protected int getCurrentDisplayAlign() { 119 return displayAlign; 120 } 121 122 protected boolean hasMoreContent() { 123 return !lm.isFinished(); 124 } 125 126 protected void addAreas(PositionIterator posIter, LayoutContext context) { 127 if (isDescendantOfTableFooter) { 128 if (repeatedHeader) { 129 context.setTreatAsArtifact(true); 130 } 131 } else { 132 if (repeatedFooter) { 133 context.setTreatAsArtifact(true); 134 } 135 } 136 AreaAdditionUtil.addAreas(lm, posIter, context); 137 } 138 139 protected void doPhase3(PageBreakingAlgorithm alg, int partCount, BlockSequence originalList, 140 BlockSequence effectiveList) { 141 if (partCount > 1) { 142 PageBreakPosition pos = alg.getPageBreaks().getFirst(); 143 int firstPartLength = ElementListUtils.calcContentLength(effectiveList, 144 effectiveList.ignoreAtStart, pos.getLeafPos()); 145 overflow += alg.totalWidth - firstPartLength; 146 } 147 // Rendering all parts (not just the first) at once for the case where the parts that 148 // overflow should be visible. 149 alg.removeAllPageBreaks(); 150 // Directly add areas after finding the breaks 151 this.addAreas(alg, 1, originalList, effectiveList); 152 } 153 154 protected void finishPart(PageBreakingAlgorithm alg, PageBreakPosition pbp) { 155 // nop for static content 156 } 157 158 protected LayoutManager getCurrentChildLM() { 159 return null; // TODO NYI 160 } 161 } 162