001: /*
002: * Licensed to the Apache Software Foundation (ASF) under one or more
003: * contributor license agreements. See the NOTICE file distributed with
004: * this work for additional information regarding copyright ownership.
005: * The ASF licenses this file to You under the Apache License, Version 2.0
006: * (the "License"); you may not use this file except in compliance with
007: * the License. You may obtain a copy of the License at
008: *
009: * http://www.apache.org/licenses/LICENSE-2.0
010: *
011: * Unless required by applicable law or agreed to in writing, software
012: * distributed under the License is distributed on an "AS IS" BASIS,
013: * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
014: * See the License for the specific language governing permissions and
015: * limitations under the License.
016: */
017:
018: /* $Id: AreaAdditionUtil.java 530724 2007-04-20 10:00:05Z vhennebert $ */
019:
020: package org.apache.fop.layoutmgr;
021:
022: import java.util.Iterator;
023: import java.util.LinkedList;
024:
025: import org.apache.fop.layoutmgr.SpaceResolver.SpaceHandlingBreakPosition;
026:
027: /**
028: * Utility class which provides common code for the addAreas stage.
029: */
030: public class AreaAdditionUtil {
031:
032: private static class StackingIter extends PositionIterator {
033: StackingIter(Iterator parentIter) {
034: super (parentIter);
035: }
036:
037: protected LayoutManager getLM(Object nextObj) {
038: return ((Position) nextObj).getLM();
039: }
040:
041: protected Position getPos(Object nextObj) {
042: return ((Position) nextObj);
043: }
044: }
045:
046: /**
047: * Creates the child areas for the given layout manager.
048: * @param bslm the BlockStackingLayoutManager instance for which "addAreas" is performed.
049: * @param parentIter the position iterator
050: * @param layoutContext the layout context
051: */
052: public static void addAreas(BlockStackingLayoutManager bslm,
053: PositionIterator parentIter, LayoutContext layoutContext) {
054: LayoutManager childLM = null;
055: LayoutContext lc = new LayoutContext(0);
056: LayoutManager firstLM = null;
057: LayoutManager lastLM = null;
058: Position firstPos = null;
059: Position lastPos = null;
060:
061: // "unwrap" the NonLeafPositions stored in parentIter
062: // and put them in a new list;
063: LinkedList positionList = new LinkedList();
064: Position pos;
065: while (parentIter.hasNext()) {
066: pos = (Position) parentIter.next();
067: if (pos == null) {
068: continue;
069: }
070: if (pos.getIndex() >= 0) {
071: if (firstPos == null) {
072: firstPos = pos;
073: }
074: lastPos = pos;
075: }
076: if (pos instanceof NonLeafPosition) {
077: // pos was created by a child of this FlowLM
078: positionList.add(((NonLeafPosition) pos).getPosition());
079: lastLM = ((NonLeafPosition) pos).getPosition().getLM();
080: if (firstLM == null) {
081: firstLM = lastLM;
082: }
083: } else if (pos instanceof SpaceHandlingBreakPosition) {
084: positionList.add(pos);
085: } else {
086: // pos was created by this LM, so it must be ignored
087: }
088: }
089: if (firstPos == null) {
090: return; //Nothing to do, return early
091: //TODO This is a hack to avoid an NPE in the code block below.
092: //If there's no firstPos/lastPos there's currently no way to
093: //correctly determine first and last conditions. The Iterator
094: //doesn't give us that info.
095: }
096:
097: if (bslm != null && bslm.markers != null) {
098: bslm.getCurrentPV().addMarkers(bslm.markers, true,
099: bslm.isFirst(firstPos), bslm.isLast(lastPos));
100: }
101:
102: StackingIter childPosIter = new StackingIter(positionList
103: .listIterator());
104: while ((childLM = childPosIter.getNextChildLM()) != null) {
105: // TODO vh: the test above might be problematic in some cases. See comment in
106: // the TableCellLM.getNextKnuthElements method
107: // Add the block areas to Area
108: lc.setFlags(LayoutContext.FIRST_AREA, childLM == firstLM);
109: lc.setFlags(LayoutContext.LAST_AREA, childLM == lastLM);
110: // set the space adjustment ratio
111: lc.setSpaceAdjust(layoutContext.getSpaceAdjust());
112: // set space before for the first LM, in order to implement
113: // display-align = center or after
114: lc.setSpaceBefore((childLM == firstLM ? layoutContext
115: .getSpaceBefore() : 0));
116: // set space after for each LM, in order to implement
117: // display-align = distribute
118: lc.setSpaceAfter(layoutContext.getSpaceAfter());
119: lc.setStackLimit(layoutContext.getStackLimit());
120: childLM.addAreas(childPosIter, lc);
121: }
122: if (bslm != null && bslm.markers != null) {
123: bslm.getCurrentPV().addMarkers(bslm.markers, false,
124: bslm.isFirst(firstPos), bslm.isLast(lastPos));
125: }
126:
127: }
128:
129: }
|