package org.apache.fop.layoutmgr;
import java.util.ArrayList;
import java.util.Collections;
import java.util.List;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.apache.fop.area.Area;
import org.apache.fop.area.AreaTreeHandler;
import org.apache.fop.area.AreaTreeModel;
import org.apache.fop.area.LineArea;
import org.apache.fop.complexscripts.bidi.BidiResolver;
import org.apache.fop.fo.Constants;
import org.apache.fop.fo.pagination.PageSequence;
import org.apache.fop.fo.pagination.PageSequenceMaster;
import org.apache.fop.fo.pagination.Region;
import org.apache.fop.fo.pagination.RegionBody;
import org.apache.fop.fo.pagination.SideRegion;
import org.apache.fop.fo.pagination.StaticContent;
import org.apache.fop.layoutmgr.inline.ContentLayoutManager;
import org.apache.fop.traits.MinOptMax;
public class PageSequenceLayoutManager extends AbstractPageSequenceLayoutManager {
private static Log log = LogFactory.getLog(PageSequenceLayoutManager.class);
private PageProvider pageProvider;
private PageBreaker pageBreaker;
private List<List<KnuthElement>> ;
private List<List<KnuthElement>> ;
private int startIntrusionAdjustment;
private int endIntrusionAdjustment;
public PageSequenceLayoutManager(AreaTreeHandler ath, PageSequence pseq) {
super(ath, pseq);
this.pageProvider = new PageProvider(ath, pseq);
}
public PageProvider getPageProvider() {
return this.pageProvider;
}
protected PageSequence getPageSequence() {
return (PageSequence)pageSeq;
}
public PageSequenceLayoutManager getPSLM() {
return this;
}
public FlowLayoutManager getFlowLayoutManager() {
if (pageBreaker == null) {
throw new IllegalStateException("This method can be called only during layout");
}
return pageBreaker.getCurrentChildLM();
}
public void activateLayout() {
initialize();
if (areaTreeHandler.isComplexScriptFeaturesEnabled()) {
BidiResolver.resolveInlineDirectionality(getPageSequence());
}
LineArea title = null;
if (getPageSequence().getTitleFO() != null) {
try {
ContentLayoutManager clm = getLayoutManagerMaker()
.makeContentLayoutManager(this, getPageSequence().getTitleFO());
Area parentArea = clm.getParentArea(null);
assert (parentArea instanceof LineArea);
title = (LineArea) parentArea;
} catch (IllegalStateException e) {
}
}
AreaTreeModel areaTreeModel = areaTreeHandler.getAreaTreeModel();
org.apache.fop.area.PageSequence pageSequenceAreaObject
= new org.apache.fop.area.PageSequence(title);
transferExtensions(pageSequenceAreaObject);
pageSequenceAreaObject.setLocale(getPageSequence().getLocale());
areaTreeModel.startPageSequence(pageSequenceAreaObject);
if (log.isDebugEnabled()) {
log.debug("Starting layout");
}
boolean finished = false;
while (!finished) {
initialize();
curPage = makeNewPage(false);
pageBreaker = new PageBreaker(this);
int flowBPD = getCurrentPV().getBodyRegion().getRemainingBPD();
finished = pageBreaker.doLayout(flowBPD);
pageProvider.skipPagePositionOnly = true;
}
finishPage();
}
public void initialize() {
super.initialize();
pageProvider.initialize();
}
public void finishPageSequence() {
if (pageSeq.hasId()) {
idTracker.signalIDProcessed(pageSeq.getId());
}
pageSeq.getRoot().notifyPageSequenceFinished(currentPageNum,
(currentPageNum - startPageNum) + 1);
areaTreeHandler.notifyPageSequenceFinished(pageSeq,
(currentPageNum - startPageNum) + 1);
getPageSequence().releasePageSequence();
String masterReference = getPageSequence().getMasterReference();
PageSequenceMaster pageSeqMaster
= pageSeq.getRoot().getLayoutMasterSet().getPageSequenceMaster(masterReference);
if (pageSeqMaster != null) {
pageSeqMaster.reset();
}
if (log.isDebugEnabled()) {
log.debug("Ending layout");
}
}
protected Page createPage(int pageNumber, boolean isBlank) {
return pageProvider.getPage(isBlank,
pageNumber, PageProvider.RELTO_PAGE_SEQUENCE);
}
@Override
protected Page makeNewPage(boolean isBlank) {
return makeNewPage(isBlank, false);
}
protected Page makeNewPage(boolean isBlank, boolean emptyContent) {
Page newPage = super.makeNewPage(isBlank);
if (!isBlank && !emptyContent) {
int i = 0;
while (!flowNameEquals(newPage, i > 0)) {
newPage = super.makeNewPage(isBlank);
i++;
}
}
return newPage;
}
private boolean flowNameEquals(Page newPage, boolean strict) {
String psName = getPageSequence().getMainFlow().getFlowName();
Region body = newPage.getSimplePageMaster().getRegion(FO_REGION_BODY);
String name = body.getRegionName();
if (strict && !name.equals(psName) && !name.equals(((RegionBody)body).getDefaultRegionName())
&& getPageSequence().hasPagePositionLast()) {
throw new RuntimeException(
"The flow-name \"" + name + "\" could not be mapped to a region-name in the layout-master-set");
}
return psName.equals(name);
}
private void layoutSideRegion(int regionID) {
SideRegion reg = (SideRegion)curPage.getSimplePageMaster().getRegion(regionID);
if (reg == null) {
return;
}
StaticContent sc = getPageSequence().getStaticContent(reg.getRegionName());
if (sc == null) {
return;
}
StaticContentLayoutManager lm = getLayoutManagerMaker()
.makeStaticContentLayoutManager(
this, sc, reg);
lm.doLayout();
}
protected void finishPage() {
layoutSideRegion(FO_REGION_BEFORE);
layoutSideRegion(FO_REGION_AFTER);
layoutSideRegion(FO_REGION_START);
layoutSideRegion(FO_REGION_END);
super.finishPage();
}
protected int getForcedLastPageNum(final int lastPageNum) {
int forcedLastPageNum = lastPageNum;
int relativeLastPage = lastPageNum - startPageNum + 1;
if (getPageSequence().getForcePageCount() == Constants.EN_EVEN) {
if (relativeLastPage % 2 != 0) {
forcedLastPageNum++;
}
} else if (getPageSequence().getForcePageCount() == Constants.EN_ODD) {
if (relativeLastPage % 2 == 0) {
forcedLastPageNum++;
}
} else if (getPageSequence().getForcePageCount() == Constants.EN_END_ON_EVEN) {
if (lastPageNum % 2 != 0) {
forcedLastPageNum++;
}
} else if (getPageSequence().getForcePageCount() == Constants.EN_END_ON_ODD) {
if (lastPageNum % 2 == 0) {
forcedLastPageNum++;
}
}
return forcedLastPageNum;
}
boolean isOnFirstPage(int partIndex) {
return pageProvider.isOnFirstPage(partIndex);
}
protected int getLastPageNumber() {
return pageProvider.getLastPageIndex();
}
protected int getWidthOfCurrentPage() {
if (curPage != null) {
return (int) curPage.getPageViewport().getViewArea().getWidth();
}
return 0;
}
public void (List<List<KnuthElement>> headerFootnotes) {
if (tableHeaderFootnotes == null) {
tableHeaderFootnotes = new ArrayList<List<KnuthElement>>();
}
tableHeaderFootnotes.addAll(headerFootnotes);
}
public List<List<KnuthElement>> () {
return getTableFootnotes(tableHeaderFootnotes);
}
public void (List<List<KnuthElement>> footerFootnotes) {
if (tableFooterFootnotes == null) {
tableFooterFootnotes = new ArrayList<List<KnuthElement>>();
}
tableFooterFootnotes.addAll(footerFootnotes);
}
public List<List<KnuthElement>> () {
return getTableFootnotes(tableFooterFootnotes);
}
private List<List<KnuthElement>> (List<List<KnuthElement>> tableFootnotes) {
if (tableFootnotes == null) {
List<List<KnuthElement>> emptyList = Collections.emptyList();
return emptyList;
} else {
return tableFootnotes;
}
}
public void () {
if (tableHeaderFootnotes != null) {
tableHeaderFootnotes.clear();
}
if (tableFooterFootnotes != null) {
tableFooterFootnotes.clear();
}
}
public void setStartIntrusionAdjustment(int sia) {
startIntrusionAdjustment = sia;
}
public void setEndIntrusionAdjustment(int eia) {
endIntrusionAdjustment = eia;
}
public int getStartIntrusionAdjustment() {
return startIntrusionAdjustment;
}
public int getEndIntrusionAdjustment() {
return endIntrusionAdjustment;
}
public void recordEndOfFloat(int fHeight) {
pageBreaker.handleEndOfFloat(fHeight);
}
public boolean handlingEndOfFloat() {
return pageBreaker.handlingEndOfFloat();
}
public int getOffsetDueToFloat() {
return pageBreaker.getOffsetDueToFloat();
}
public void recordStartOfFloat(int fHeight, int fYOffset) {
pageBreaker.handleStartOfFloat(fHeight, fYOffset);
}
public boolean handlingStartOfFloat() {
return pageBreaker.handlingStartOfFloat();
}
public int getFloatHeight() {
return pageBreaker.getFloatHeight();
}
public int getFloatYOffset() {
return pageBreaker.getFloatYOffset();
}
public int getCurrentColumnWidth() {
int flowIPD = getCurrentPV().getCurrentSpan().getColumnWidth();
flowIPD -= startIntrusionAdjustment + endIntrusionAdjustment;
return flowIPD;
}
public void (List fl, List ll, int tfl, int ifl, boolean fp, boolean nf, int fnfi, int fli,
int fei, MinOptMax fsl, int pfli, int pfei) {
if (fl != null && fl.size() > 0) {
pageBreaker.holdFootnotes(fl, ll, tfl, ifl, fp, nf, fnfi, fli, fei, fsl, pfli, pfei);
}
}
public void (PageBreakingAlgorithm alg) {
pageBreaker.retrieveFootones(alg);
}
}