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: ContentLayoutManager.java 453310 2006-10-05 18:44:15Z spepping $ */
019:
020: package org.apache.fop.layoutmgr.inline;
021:
022: import org.apache.commons.logging.Log;
023: import org.apache.commons.logging.LogFactory;
024: import org.apache.fop.apps.FOUserAgent;
025: import org.apache.fop.fo.Constants;
026: import org.apache.fop.fo.pagination.Title;
027: import org.apache.fop.layoutmgr.AbstractBaseLayoutManager;
028: import org.apache.fop.layoutmgr.KnuthElement;
029: import org.apache.fop.layoutmgr.KnuthPossPosIter;
030: import org.apache.fop.layoutmgr.KnuthSequence;
031: import org.apache.fop.layoutmgr.LayoutContext;
032: import org.apache.fop.layoutmgr.LayoutManager;
033: import org.apache.fop.layoutmgr.PageSequenceLayoutManager;
034: import org.apache.fop.layoutmgr.Position;
035: import org.apache.fop.layoutmgr.PositionIterator;
036: import org.apache.fop.layoutmgr.SpaceSpecifier;
037: import org.apache.fop.area.Area;
038: import org.apache.fop.area.LineArea;
039: import org.apache.fop.area.inline.InlineArea;
040:
041: import java.util.LinkedList;
042: import java.util.List;
043: import java.util.ListIterator;
044: import java.util.ArrayList;
045: import java.util.Iterator;
046: import org.apache.fop.traits.MinOptMax;
047:
048: import org.apache.fop.area.Block;
049:
050: /**
051: * Content Layout Manager.
052: * For use with objects that contain inline areas such as
053: * leader use-content and title.
054: */
055: public class ContentLayoutManager extends AbstractBaseLayoutManager
056: implements InlineLevelLayoutManager {
057:
058: /**
059: * logging instance
060: */
061: private static Log log = LogFactory
062: .getLog(ContentLayoutManager.class);
063:
064: private FOUserAgent userAgent;
065: private Area holder;
066: private int stackSize;
067: private LayoutManager parentLM;
068: private InlineLevelLayoutManager childLM = null;
069:
070: /**
071: * Constructs a new ContentLayoutManager
072: *
073: * @param area The parent area
074: */
075: public ContentLayoutManager(Area area, LayoutManager parentLM) {
076: holder = area;
077: this .parentLM = parentLM;
078: }
079:
080: /**
081: * Constructor using a fo:title formatting object and its PageSequenceLayoutManager parent.
082: * throws IllegalStateException if the foTitle has no children.
083: * TODO: convert IllegalStateException to FOPException;
084: * also in makeLayoutManager and makeContentLayoutManager and callers.
085: * @param pslm the PageSequenceLayoutManager parent of this LM
086: * @param foTitle the Title FO for which this LM is made
087: */
088: public ContentLayoutManager(PageSequenceLayoutManager pslm,
089: Title foTitle) {
090: // get breaks then add areas to title
091: this .parentLM = pslm;
092: holder = new LineArea();
093:
094: // setUserAgent(foTitle.getUserAgent());
095:
096: // use special layout manager to add the inline areas
097: // to the Title.
098: try {
099: LayoutManager lm = pslm.getLayoutManagerMaker()
100: .makeLayoutManager(foTitle);
101: addChildLM(lm);
102: fillArea(lm);
103: } catch (IllegalStateException e) {
104: log.warn("Title has no content");
105: throw e;
106: }
107: }
108:
109: public void initialize() {
110: // Empty
111: }
112:
113: public void fillArea(LayoutManager curLM) {
114:
115: int ipd = 1000000;
116:
117: LayoutContext childLC = new LayoutContext(
118: LayoutContext.NEW_AREA);
119: childLC.setLeadingSpace(new SpaceSpecifier(false));
120: childLC.setTrailingSpace(new SpaceSpecifier(false));
121: // set stackLimit for lines
122: childLC.setStackLimit(new MinOptMax(ipd));
123: childLC.setRefIPD(ipd);
124:
125: int lineHeight = 14000;
126: int lead = 12000;
127: int follow = 2000;
128:
129: int halfLeading = (lineHeight - lead - follow) / 2;
130: // height before baseline
131: int lineLead = lead + halfLeading;
132: // maximum size of top and bottom alignment
133: int maxtb = follow + halfLeading;
134: // max size of middle alignment below baseline
135: int middlefollow = maxtb;
136:
137: stackSize = 0;
138:
139: LinkedList contentList = getNextKnuthElements(childLC,
140: Constants.EN_START);
141: ListIterator contentIter = contentList.listIterator();
142: while (contentIter.hasNext()) {
143: KnuthElement element = (KnuthElement) contentIter.next();
144: if (element instanceof KnuthInlineBox) {
145: KnuthInlineBox box = (KnuthInlineBox) element;
146: // TODO handle alignment here?
147: }
148: }
149:
150: if (maxtb - lineLead > middlefollow) {
151: middlefollow = maxtb - lineLead;
152: }
153:
154: LayoutContext lc = new LayoutContext(0);
155:
156: lc.setFlags(LayoutContext.RESOLVE_LEADING_SPACE, true);
157: lc.setLeadingSpace(new SpaceSpecifier(false));
158: lc.setTrailingSpace(new SpaceSpecifier(false));
159: KnuthPossPosIter contentPosIter = new KnuthPossPosIter(
160: contentList, 0, contentList.size());
161: curLM.addAreas(contentPosIter, lc);
162: }
163:
164: public void addAreas(PositionIterator posIter, LayoutContext context) {
165: // add the content areas
166: // the area width has already been adjusted, and it must remain unchanged
167: // so save its value before calling addAreas, and set it again afterwards
168: int savedIPD = ((InlineArea) holder).getIPD();
169: // set to zero the ipd adjustment ratio, to avoid spaces in the pattern
170: // to be modified
171: LayoutContext childContext = new LayoutContext(context);
172: childContext.setIPDAdjust(0.0);
173: childLM.addAreas(posIter, childContext);
174: ((InlineArea) holder).setIPD(savedIPD);
175: }
176:
177: public int getStackingSize() {
178: return stackSize;
179: }
180:
181: /** @see org.apache.fop.layoutmgr.LayoutManager */
182: public Area getParentArea(Area childArea) {
183: return holder;
184: }
185:
186: /**
187: * @see org.apache.fop.layoutmgr.LayoutManager#addChildArea(Area)
188: **/
189: public void addChildArea(Area childArea) {
190: holder.addChildArea(childArea);
191: }
192:
193: /**
194: * @see org.apache.fop.layoutmgr.LayoutManager#setParent(LayoutManager)
195: */
196: public void setParent(LayoutManager lm) {
197: parentLM = lm;
198: }
199:
200: /** @see org.apache.fop.layoutmgr.LayoutManager#getParent() */
201: public LayoutManager getParent() {
202: return this .parentLM;
203: }
204:
205: /**
206: * @see org.apache.fop.layoutmgr.LayoutManager#isFinished()
207: */
208: public boolean isFinished() {
209: return false;
210: }
211:
212: /**
213: * @see org.apache.fop.layoutmgr.LayoutManager#setFinished(boolean)
214: */
215: public void setFinished(boolean isFinished) {
216: //to be done
217: }
218:
219: /**
220: * @see org.apache.fop.layoutmgr.LayoutManager#resetPosition(Position)
221: */
222: public void resetPosition(Position position) {
223: //to be done
224: }
225:
226: /**
227: * @see org.apache.fop.layoutmgr.LayoutManager#createNextChildLMs(int)
228: */
229: public boolean createNextChildLMs(int pos) {
230: return false;
231: }
232:
233: /**
234: * @see org.apache.fop.layoutmgr.LayoutManager#getChildLMs()
235: */
236: public List getChildLMs() {
237: List childLMs = new ArrayList(1);
238: childLMs.add(childLM);
239: return childLMs;
240: }
241:
242: /**
243: * @see org.apache.fop.layoutmgr.LayoutManager#addChildLM
244: */
245: public void addChildLM(LayoutManager lm) {
246: if (lm == null) {
247: return;
248: }
249: lm.setParent(this );
250: childLM = (InlineLevelLayoutManager) lm;
251: log.trace(this .getClass().getName() + ": Adding child LM "
252: + lm.getClass().getName());
253: }
254:
255: /**
256: * @see org.apache.fop.layoutmgr.LayoutManager#addChildLMs
257: */
258: public void addChildLMs(List newLMs) {
259: if (newLMs == null || newLMs.size() == 0) {
260: return;
261: }
262: ListIterator iter = newLMs.listIterator();
263: while (iter.hasNext()) {
264: LayoutManager lm = (LayoutManager) iter.next();
265: addChildLM(lm);
266: }
267: }
268:
269: public LinkedList getNextKnuthElements(LayoutContext context,
270: int alignment) {
271: LinkedList contentList = new LinkedList();
272: LinkedList returnedList;
273:
274: childLM.initialize();
275: while (!childLM.isFinished()) {
276: // get KnuthElements from childLM
277: returnedList = childLM.getNextKnuthElements(context,
278: alignment);
279:
280: if (returnedList != null) {
281: // move elements to contentList, and accumulate their size
282: KnuthElement contentElement;
283: while (returnedList.size() > 0) {
284: Object obj = returnedList.removeFirst();
285: if (obj instanceof KnuthSequence) {
286: KnuthSequence ks = (KnuthSequence) obj;
287: for (Iterator it = ks.iterator(); it.hasNext();) {
288: contentElement = (KnuthElement) it.next();
289: stackSize += contentElement.getW();
290: contentList.add(contentElement);
291: }
292: } else {
293: contentElement = (KnuthElement) obj;
294: stackSize += contentElement.getW();
295: contentList.add(contentElement);
296: }
297: }
298: }
299: }
300:
301: setFinished(true);
302: return contentList;
303: }
304:
305: public List addALetterSpaceTo(List oldList) {
306: return oldList;
307: }
308:
309: /**
310: * Remove the word space represented by the given elements
311: *
312: * @param oldList the elements representing the word space
313: */
314: public void removeWordSpace(List oldList) {
315: // do nothing
316: log
317: .warn(this .getClass().getName()
318: + " should not receive a call to removeWordSpace(list)");
319: }
320:
321: public void getWordChars(StringBuffer sbChars, Position pos) {
322: }
323:
324: public void hyphenate(Position pos, HyphContext hc) {
325: }
326:
327: public boolean applyChanges(List oldList) {
328: return false;
329: }
330:
331: public LinkedList getChangedKnuthElements(List oldList,
332: /*int flaggedPenalty,*/
333: int alignment) {
334: return null;
335: }
336:
337: public PageSequenceLayoutManager getPSLM() {
338: return parentLM.getPSLM();
339: }
340:
341: // --------- Property Resolution related functions --------- //
342:
343: /**
344: * Returns the IPD of the content area
345: * @return the IPD of the content area
346: */
347: public int getContentAreaIPD() {
348: return holder.getIPD();
349: }
350:
351: /**
352: * Returns the BPD of the content area
353: * @return the BPD of the content area
354: */
355: public int getContentAreaBPD() {
356: return holder.getBPD();
357: }
358:
359: /**
360: * @see org.apache.fop.layoutmgr.LayoutManager#getGeneratesReferenceArea
361: */
362: public boolean getGeneratesReferenceArea() {
363: return false;
364: }
365:
366: /**
367: * @see org.apache.fop.layoutmgr.LayoutManager#getGeneratesBlockArea
368: */
369: public boolean getGeneratesBlockArea() {
370: return getGeneratesLineArea() || holder instanceof Block;
371: }
372:
373: /**
374: * @see org.apache.fop.layoutmgr.LayoutManager#getGeneratesLineArea
375: */
376: public boolean getGeneratesLineArea() {
377: return holder instanceof LineArea;
378: }
379:
380: /* (non-Javadoc)
381: * @see org.apache.fop.layoutmgr.LayoutManager#notifyPos(org.apache.fop.layoutmgr.Position)
382: */
383: public Position notifyPos(Position pos) {
384: return pos;
385: }
386:
387: }
|