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