blob: c7eaa1820844380928e52b73ce1b64f524bfb849 [file] [log] [blame]
/*
* Licensed to the Apache Software Foundation (ASF) under one or more
* contributor license agreements. See the NOTICE file distributed with
* this work for additional information regarding copyright ownership.
* The ASF licenses this file to You under the Apache License, Version 2.0
* (the "License"); you may not use this file except in compliance with
* the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
/* $Id$ */
package org.apache.fop.layoutmgr.inline;
import java.util.ArrayList;
import java.util.Iterator;
import java.util.LinkedList;
import java.util.List;
import java.util.ListIterator;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.apache.fop.area.Area;
import org.apache.fop.area.Block;
import org.apache.fop.area.LineArea;
import org.apache.fop.area.inline.InlineArea;
import org.apache.fop.fo.Constants;
import org.apache.fop.fo.pagination.Title;
import org.apache.fop.layoutmgr.AbstractBaseLayoutManager;
import org.apache.fop.layoutmgr.KnuthElement;
import org.apache.fop.layoutmgr.KnuthPossPosIter;
import org.apache.fop.layoutmgr.KnuthSequence;
import org.apache.fop.layoutmgr.LayoutContext;
import org.apache.fop.layoutmgr.LayoutManager;
import org.apache.fop.layoutmgr.PageSequenceLayoutManager;
import org.apache.fop.layoutmgr.Position;
import org.apache.fop.layoutmgr.PositionIterator;
import org.apache.fop.layoutmgr.SpaceSpecifier;
/**
* Content Layout Manager.
* For use with objects that contain inline areas such as
* leader use-content and title.
*/
public class ContentLayoutManager extends AbstractBaseLayoutManager
implements InlineLevelLayoutManager {
/**
* logging instance
*/
private static Log log = LogFactory.getLog(ContentLayoutManager.class);
private Area holder;
private int stackSize;
private LayoutManager parentLM;
private InlineLevelLayoutManager childLM = null;
/**
* Constructs a new ContentLayoutManager
*
* @param area The parent area
* @param parentLM the parent layout manager
*/
public ContentLayoutManager(Area area, LayoutManager parentLM) {
holder = area;
this.parentLM = parentLM;
}
/**
* Constructor using a fo:title formatting object and its PageSequenceLayoutManager parent.
* throws IllegalStateException if the foTitle has no children.
* TODO: convert IllegalStateException to FOPException;
* also in makeLayoutManager and makeContentLayoutManager and callers.
* @param pslm the PageSequenceLayoutManager parent of this LM
* @param foTitle the Title FO for which this LM is made
*/
public ContentLayoutManager(PageSequenceLayoutManager pslm, Title foTitle) {
// get breaks then add areas to title
this.parentLM = pslm;
holder = new LineArea();
// setUserAgent(foTitle.getUserAgent());
// use special layout manager to add the inline areas
// to the Title.
try {
LayoutManager lm = pslm.getLayoutManagerMaker().makeLayoutManager(foTitle);
addChildLM(lm);
fillArea(lm);
} catch (IllegalStateException e) {
log.warn("Title has no content");
throw e;
}
}
/** {@inheritDoc} */
public void initialize() {
// Empty
}
private void fillArea(LayoutManager curLM) {
int ipd = 1000000;
LayoutContext childLC = new LayoutContext(LayoutContext.NEW_AREA);
childLC.setLeadingSpace(new SpaceSpecifier(false));
childLC.setTrailingSpace(new SpaceSpecifier(false));
childLC.setRefIPD(ipd);
int lineHeight = 14000;
int lead = 12000;
int follow = 2000;
int halfLeading = (lineHeight - lead - follow) / 2;
// height before baseline
int lineLead = lead + halfLeading;
// maximum size of top and bottom alignment
int maxtb = follow + halfLeading;
// max size of middle alignment below baseline
int middlefollow = maxtb;
stackSize = 0;
List contentList = getNextKnuthElements(childLC, Constants.EN_START);
ListIterator contentIter = contentList.listIterator();
while (contentIter.hasNext()) {
KnuthElement element = (KnuthElement) contentIter.next();
if (element instanceof KnuthInlineBox) {
KnuthInlineBox box = (KnuthInlineBox) element;
// TODO handle alignment here?
}
}
if (maxtb - lineLead > middlefollow) {
middlefollow = maxtb - lineLead;
}
LayoutContext lc = new LayoutContext(0);
lc.setFlags(LayoutContext.RESOLVE_LEADING_SPACE, true);
lc.setLeadingSpace(new SpaceSpecifier(false));
lc.setTrailingSpace(new SpaceSpecifier(false));
KnuthPossPosIter contentPosIter = new KnuthPossPosIter(contentList, 0, contentList.size());
curLM.addAreas(contentPosIter, lc);
}
/** {@inheritDoc} */
public void addAreas(PositionIterator posIter, LayoutContext context) {
// add the content areas
// the area width has already been adjusted, and it must remain unchanged
// so save its value before calling addAreas, and set it again afterwards
int savedIPD = ((InlineArea)holder).getIPD();
// set to zero the ipd adjustment ratio, to avoid spaces in the pattern
// to be modified
LayoutContext childContext = new LayoutContext(context);
childContext.setIPDAdjust(0.0);
childLM.addAreas(posIter, childContext);
((InlineArea)holder).setIPD(savedIPD);
}
/** @return stack size */
public int getStackingSize() {
return stackSize;
}
/** {@inheritDoc} */
public Area getParentArea(Area childArea) {
return holder;
}
/**
* {@inheritDoc}
**/
public void addChildArea(Area childArea) {
holder.addChildArea(childArea);
}
/**
* {@inheritDoc}
*/
public void setParent(LayoutManager lm) {
parentLM = lm;
}
/** {@inheritDoc} */
public LayoutManager getParent() {
return this.parentLM;
}
/**
* {@inheritDoc}
*/
public boolean isFinished() {
return false;
}
/**
* {@inheritDoc}
*/
public void setFinished(boolean isFinished) {
//to be done
}
/**
* {@inheritDoc}
*/
public boolean createNextChildLMs(int pos) {
return false;
}
/**
* {@inheritDoc}
*/
public List getChildLMs() {
List childLMs = new ArrayList(1);
childLMs.add(childLM);
return childLMs;
}
/**
* {@inheritDoc}
*/
public void addChildLM(LayoutManager lm) {
if (lm == null) {
return;
}
lm.setParent(this);
childLM = (InlineLevelLayoutManager)lm;
log.trace(this.getClass().getName()
+ ": Adding child LM " + lm.getClass().getName());
}
/**
* {@inheritDoc}
*/
public void addChildLMs(List newLMs) {
if (newLMs == null || newLMs.size() == 0) {
return;
}
ListIterator iter = newLMs.listIterator();
while (iter.hasNext()) {
LayoutManager lm = (LayoutManager) iter.next();
addChildLM(lm);
}
}
/** {@inheritDoc} */
public List getNextKnuthElements(LayoutContext context, int alignment) {
List contentList = new LinkedList();
List returnedList;
childLM.initialize();
while (!childLM.isFinished()) {
// get KnuthElements from childLM
returnedList = childLM.getNextKnuthElements(context, alignment);
if (returnedList != null) {
// move elements to contentList, and accumulate their size
KnuthElement contentElement;
while (returnedList.size() > 0) {
Object obj = returnedList.remove(0);
if (obj instanceof KnuthSequence) {
KnuthSequence ks = (KnuthSequence)obj;
for (Iterator it = ks.iterator(); it.hasNext();) {
contentElement = (KnuthElement)it.next();
stackSize += contentElement.getWidth();
contentList.add(contentElement);
}
} else {
contentElement = (KnuthElement)obj;
stackSize += contentElement.getWidth();
contentList.add(contentElement);
}
}
}
}
setFinished(true);
return contentList;
}
/** {@inheritDoc} */
public List addALetterSpaceTo(List oldList) {
return oldList;
}
/** {@inheritDoc} */
public List addALetterSpaceTo(List oldList, int depth) {
return addALetterSpaceTo(oldList);
}
/** {@inheritDoc} */
public String getWordChars(Position pos) {
return "";
}
/** {@inheritDoc} */
public void hyphenate(Position pos, HyphContext hc) {
}
/** {@inheritDoc} */
public boolean applyChanges(List oldList) {
return false;
}
/** {@inheritDoc} */
public boolean applyChanges(List oldList, int depth) {
return applyChanges(oldList);
}
/** {@inheritDoc} */
public List getChangedKnuthElements(List oldList, int alignment) {
return null;
}
/** {@inheritDoc} */
public List getChangedKnuthElements(List oldList, int alignment, int depth) {
return getChangedKnuthElements(oldList, alignment);
}
/** {@inheritDoc} */
public PageSequenceLayoutManager getPSLM() {
return parentLM.getPSLM();
}
// --------- Property Resolution related functions --------- //
/**
* Returns the IPD of the content area
* @return the IPD of the content area
*/
public int getContentAreaIPD() {
return holder.getIPD();
}
/**
* Returns the BPD of the content area
* @return the BPD of the content area
*/
public int getContentAreaBPD() {
return holder.getBPD();
}
/**
* {@inheritDoc}
*/
public boolean getGeneratesReferenceArea() {
return false;
}
/**
* {@inheritDoc}
*/
public boolean getGeneratesBlockArea() {
return getGeneratesLineArea() || holder instanceof Block;
}
/**
* {@inheritDoc}
*/
public boolean getGeneratesLineArea() {
return holder instanceof LineArea;
}
/**
* {@inheritDoc}
*/
public Position notifyPos(Position pos) {
return pos;
}
}