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 package org.apache.fop.layoutmgr; 20 21 import java.util.Collections; 22 import java.util.Iterator; 23 import java.util.LinkedList; 24 25 import org.apache.fop.events.EventBroadcaster; 26 27 /** 28 * Class to find the restart layoutmanager for changing IPD 29 */ 30 class RestartAtLM { 31 protected boolean invalidPosition; 32 getRestartAtLM(AbstractBreaker breaker, PageBreakingAlgorithm alg, boolean ipdChangesOnNextPage, boolean onLastPageAndIPDChanges, boolean visitedBefore, AbstractBreaker.BlockSequence blockList, int start)33 protected LayoutManager getRestartAtLM(AbstractBreaker breaker, PageBreakingAlgorithm alg, 34 boolean ipdChangesOnNextPage, boolean onLastPageAndIPDChanges, 35 boolean visitedBefore, AbstractBreaker.BlockSequence blockList, int start) { 36 BreakingAlgorithm.KnuthNode optimalBreak = ipdChangesOnNextPage ? alg.getBestNodeBeforeIPDChange() : alg 37 .getBestNodeForLastPage(); 38 if (onLastPageAndIPDChanges && visitedBefore && breaker.originalRestartAtLM == null) { 39 optimalBreak = null; 40 } 41 int positionIndex = findPositionIndex(breaker, optimalBreak, alg, start); 42 if (ipdChangesOnNextPage || (breaker.positionAtBreak != null && breaker.positionAtBreak.getIndex() > -1)) { 43 breaker.firstElementsForRestart = Collections.EMPTY_LIST; 44 if (ipdChangesOnNextPage) { 45 if (breaker.containsNonRestartableLM(breaker.positionAtBreak)) { 46 if (alg.getIPDdifference() > 0) { 47 EventBroadcaster eventBroadcaster = breaker.getCurrentChildLM().getFObj() 48 .getUserAgent().getEventBroadcaster(); 49 BlockLevelEventProducer eventProducer = BlockLevelEventProducer.Provider 50 .get(eventBroadcaster); 51 eventProducer.nonRestartableContentFlowingToNarrowerPage(this); 52 } 53 breaker.firstElementsForRestart = new LinkedList(); 54 boolean boxFound = false; 55 Iterator iter = blockList.listIterator(positionIndex + 1); 56 Position position = null; 57 while (iter.hasNext() 58 && (position == null || breaker.containsNonRestartableLM(position))) { 59 positionIndex++; 60 KnuthElement element = (KnuthElement) iter.next(); 61 position = element.getPosition(); 62 if (element.isBox()) { 63 boxFound = true; 64 breaker.firstElementsForRestart.add(element); 65 } else if (boxFound) { 66 breaker.firstElementsForRestart.add(element); 67 } 68 } 69 if (position instanceof SpaceResolver.SpaceHandlingBreakPosition) { 70 /* Retrieve the original position wrapped into this space position */ 71 breaker.positionAtBreak = position.getPosition(); 72 } else { 73 breaker.positionAtBreak = null; 74 } 75 } 76 } 77 } 78 LayoutManager restartAtLM = null; 79 if (ipdChangesOnNextPage || !(breaker.positionAtBreak != null && breaker.positionAtBreak.getIndex() > -1)) { 80 if (breaker.positionAtBreak != null && breaker.positionAtBreak.getIndex() == -1) { 81 Position position; 82 Iterator iter = blockList.listIterator(positionIndex + 1); 83 do { 84 KnuthElement nextElement = (KnuthElement) iter.next(); 85 position = nextElement.getPosition(); 86 } while (position == null 87 || position instanceof SpaceResolver.SpaceHandlingPosition 88 || position instanceof SpaceResolver.SpaceHandlingBreakPosition 89 && position.getPosition().getIndex() == -1); 90 LayoutManager surroundingLM = breaker.positionAtBreak.getLM(); 91 while (position.getLM() != surroundingLM) { 92 position = position.getPosition(); 93 } 94 if (position.getPosition() == null) { 95 position.getLM().getFObj().setForceKeepTogether(true); 96 invalidPosition = true; 97 return null; 98 } 99 restartAtLM = position.getPosition().getLM(); 100 } 101 if (onLastPageAndIPDChanges && restartAtLM != null) { 102 if (breaker.originalRestartAtLM == null) { 103 breaker.originalRestartAtLM = restartAtLM; 104 } else { 105 restartAtLM = breaker.originalRestartAtLM; 106 } 107 breaker.firstElementsForRestart = Collections.EMPTY_LIST; 108 } 109 } 110 if (onLastPageAndIPDChanges && !visitedBefore && breaker.positionAtBreak.getPosition() != null) { 111 restartAtLM = breaker.positionAtBreak.getPosition().getLM(); 112 } 113 return restartAtLM; 114 } 115 findPositionIndex(AbstractBreaker breaker, BreakingAlgorithm.KnuthNode optimalBreak, PageBreakingAlgorithm alg, int start)116 private int findPositionIndex(AbstractBreaker breaker, BreakingAlgorithm.KnuthNode optimalBreak, 117 PageBreakingAlgorithm alg, int start) { 118 int positionIndex = (optimalBreak != null) ? optimalBreak.position : start; 119 for (int i = positionIndex; i < alg.par.size(); i++) { 120 KnuthElement elementAtBreak = alg.getElement(i); 121 if (elementAtBreak.getPosition() == null) { 122 elementAtBreak = alg.getElement(0); 123 } 124 breaker.positionAtBreak = elementAtBreak.getPosition(); 125 /* Retrieve the original position wrapped into this space position */ 126 breaker.positionAtBreak = breaker.positionAtBreak.getPosition(); 127 if (breaker.positionAtBreak != null) { 128 return i; 129 } 130 } 131 return positionIndex; 132 } 133 } 134