From 33c605ec16b366fb1a064a8258a450e5b4c249b3 Mon Sep 17 00:00:00 2001 From: Karen Lease Date: Sun, 11 Nov 2001 14:13:51 +0000 Subject: [PATCH] new layout managers git-svn-id: https://svn.apache.org/repos/asf/xmlgraphics/fop/trunk@194557 13f79535-47bb-0310-9956-ffa450edef68 --- .../fop/layoutmgr/BlockLayoutManager.java | 144 ++++++++++++++++ .../fop/layoutmgr/LineLayoutManager.java | 161 ++++++++++++++++++ .../fop/layoutmgr/TextLayoutManager.java | 73 ++++++++ 3 files changed, 378 insertions(+) create mode 100644 src/org/apache/fop/layoutmgr/BlockLayoutManager.java create mode 100644 src/org/apache/fop/layoutmgr/LineLayoutManager.java create mode 100644 src/org/apache/fop/layoutmgr/TextLayoutManager.java diff --git a/src/org/apache/fop/layoutmgr/BlockLayoutManager.java b/src/org/apache/fop/layoutmgr/BlockLayoutManager.java new file mode 100644 index 000000000..7b4bfbc80 --- /dev/null +++ b/src/org/apache/fop/layoutmgr/BlockLayoutManager.java @@ -0,0 +1,144 @@ +/* + * $Id$ + * Copyright (C) 2001 The Apache Software Foundation. All rights reserved. + * For details on use and redistribution please refer to the + * LICENSE file included with these sources. + */ + +package org.apache.fop.layoutmgr; + +import org.apache.fop.fo.FObj; +import org.apache.fop.area.Area; +import org.apache.fop.area.BlockParent; +import org.apache.fop.area.Block; +import org.apache.fop.area.LineArea; + +import java.util.ListIterator; + +/** + * LayoutManager for a block FO. + */ +public class BlockLayoutManager extends BlockStackingLayoutManager { + + private Block curBlockArea; + + public BlockLayoutManager(FObj fobj) { + super(fobj); + } + + // DESIGN. Potential alternative to getParentArea() scheme +// /** +// * Called by child layout manager to get the available space for +// * content in the inline progression direction. +// * Note that a manager may need to ask its parent for this. +// * For a block area, available IPD is determined by indents. +// */ +// public int getContentIPD() { +// getArea(); // make if not existing +// return blockArea.getIPD(); +// } + + /** + * Generate areas by tellings all layout managers for its FO's + * children to generate areas. + */ + public void generateAreas() { + ListIterator children = fobj.getChildren(); + while (children.hasNext()) { + LayoutManager lm = ((FObj)children.next()).getLayoutManager(); + if (lm != null) { + if (lm.generatesInlineAreas()) { + // Back up one + children.previous(); + lm = new LineLayoutManager(children); + } + lm.setParentLM(this); + lm.generateAreas(); + } + } + flush(); // Add last area to parent + } + + + /** + * Return an Area which can contain the passed childArea. The childArea + * may not yet have any content, but it has essential traits set. + * In general, if the LayoutManager already has an Area it simply returns + * it. Otherwise, it makes a new Area of the appropriate class. + * It gets a parent area for its area by calling its parent LM. + * Finally, based on the dimensions of the parent area, it initializes + * its own area. This includes setting the content IPD and the maximum + * BPD. + */ + public Area getParentArea(Area childArea) { + if (curBlockArea == null) { + curBlockArea = new Block(); + // Set up dimensions + // Must get dimensions from parent area + //MinOptMax referenceIPD = parentLM.getReferenceIPD(); + Area parentArea = parentLM.getParentArea(curBlockArea); + // Get reference IPD from parentArea + setCurrentArea(curBlockArea); // ??? for generic operations + } + return curBlockArea; + } + + + public void addChild(Area childArea) { + if (curBlockArea != null) { + if (childArea instanceof LineArea) { + // Something about widows and orphans + // Position the line area and calculate size... + curBlockArea.addLineArea((LineArea)childArea); + } + else { + super.addChild(childArea); + } + } + } + + + +// /** +// * Called by child LayoutManager when it has filled one of its areas. +// * If no current container, make one. +// * See if the area will fit in the current container. +// * If so, add it. +// * @param childArea the area to add: will either be a LineArea or +// * a BlockArea. +// */ +// public void addChild(Area childArea) { +// /* If the childArea fits entirely in the maximum available BPD +// * add it and return an OK status. +// * If it doesn't all fit, overrun or ask for split? +// * Might as well just add it since the page layout process +// * may need to make other adjustments, resulting in changing +// * split point. +// */ +// // Things like breaks on child area can cause premature +// // termination of the current area. +// /* We go past the theoretical maximum to be able to handle things +// * like widows. +// */ +// // WARNING: this doesn't take into account space-specifier +// // adujstment between childArea and last content of blockArea! +// if (blockArea.getContentBPD().min + childArea.getAllocationBPD().min +// > blockArea.getAvailBPD().max) { +// if (++extraLines <= iWidows) { +// blockArea.add(childArea); +// } +// else { +// blockArea.setIsLast(false); +// parentLM.addChildArea(blockArea); +// // Make a new one for this area +// blockArea = makeAreaForChild(childArea); +// extraLines = 0; // Count potential widows +// blockArea.add(childArea); +// } +// } +// else { +// blockArea.add(childArea); +// } +// } + +} diff --git a/src/org/apache/fop/layoutmgr/LineLayoutManager.java b/src/org/apache/fop/layoutmgr/LineLayoutManager.java new file mode 100644 index 000000000..38451354b --- /dev/null +++ b/src/org/apache/fop/layoutmgr/LineLayoutManager.java @@ -0,0 +1,161 @@ +/* + * $Id$ + * Copyright (C) 2001 The Apache Software Foundation. All rights reserved. + * For details on use and redistribution please refer to the + * LICENSE file included with these sources. + */ + +package org.apache.fop.layoutmgr; + + +import org.apache.fop.fo.FObj; +import org.apache.fop.area.Area; +import org.apache.fop.area.LineArea; +import org.apache.fop.area.MinOptMax; +import org.apache.fop.area.inline.InlineArea; + +import java.util.ListIterator; + +/** + * LayoutManager for lines. It builds one or more lines containing + * inline areas generated by its sub layout managers. + */ +public class LineLayoutManager extends AbstractLayoutManager { + /** Reference to FO whose areas it's managing or to the traits + * of the FO. + */ + private ListIterator fobjIter; + private LineArea lineArea = null; + private boolean bFirstLine; + private LayoutManager curLM; + private MinOptMax remainingIPD; + + public LineLayoutManager(ListIterator fobjIter) { + super(null); + this.fobjIter = fobjIter; + } + + + /** + * Call child layout managers to generate content as long as they + * generate inline areas. If a block-level generating LM is found, + * finish any line being filled and return to the parent LM. + */ + public void generateAreas() { + this.bFirstLine = true; + while (fobjIter.hasNext()) { + FObj fobj = (FObj)fobjIter.next(); + curLM = fobj.getLayoutManager(); + if (curLM != null) { + if (curLM.generatesInlineAreas()==false) { + // It generates blocks, pass back to parent + // Back up one + fobjIter.previous(); + break; + } + else { // generates inline area + curLM.setParentLM(this); + curLM.generateAreas(); + } + } + } + flush(); // Add last area to parent + } + + + /** + * Align and position curLine and add it to parentContainer. + * Set curLine to null. + */ + public void flush() { + if (lineArea != null) { + // Adjust spacing as necessary + // Calculate height, based on content (or does the Area do this?) + parentLM.addChild(lineArea); + lineArea = null; + } + } + + + /** + * Return current lineArea or generate a new one if necessary. + */ + public Area getParentArea(Area childArea) { + if (lineArea == null) { + createLine(); + } + return lineArea; + } + + private void createLine() { + lineArea = new LineArea(); + /* Set line IPD from parentArea + * This accounts for indents. What about first line indent? + * Should we set an "isFirst" flag on the lineArea to signal + * that to the parent (Block) LM? That's where indent property + * information will be managed. + */ + Area parent = parentLM.getParentArea(lineArea); + // lineArea.setContentIPD(parent.getContentIPD()); + // remainingIPD = parent.getContentIPD(); + // OR??? + // remainingIPD = parentLM.getContentIPD(); + remainingIPD = new MinOptMax(100000); // TESTING!!! + this.bFirstLine = false; + } + + + /** + * Called by child LayoutManager when it has filled one of its areas. + * See if the area will fit in the current container. + * If so, add it. + * This should also handle floats if childArea is an anchor. + * @param childArea the area to add: should be an InlineArea subclass! + */ + public void addChild(Area childArea) { + if ((childArea instanceof InlineArea)==false) { + // SIGNAL AN ERROR!!! + return; + } + InlineArea inlineArea = (InlineArea)childArea; + if (lineArea == null) { + createLine(); + } + if (inlineArea.getAllocationIPD().min < remainingIPD.max) { + lineArea.addInlineArea(inlineArea); + remainingIPD.subtract(inlineArea.getAllocationIPD()); + // Calculate number of spaces + // Forced line break after this area (ex. ends with LF in nowrap) + /* NOTYET! + if (inlineArea.breakAfter()) { + flush(); + } + */ + /* Check if line could end after this area (potential line-break + * character. If not, it must be joined with following inline + * area to make a word. Otherwise, if the line could break here + * and if it is "full", add it to the parent area. + */ + if (remainingIPD.min<=0) { + flush(); + } + } + + else { + /* The inline area won't entirely fit in this line. Ask its + * layout manager to split it (by hyphenation for example), + * in order to fit part of it in the line. + * Note: only the current child LM could have generated this + * area, so we ask it to do the split. + */ + SplitContext splitContext = new SplitContext(remainingIPD); + if (curLM.splitArea(inlineArea, splitContext)) { + // inlineArea should now fit + lineArea.addInlineArea(inlineArea); + flush(); + } + addChild(splitContext.nextArea); + } + } + +} diff --git a/src/org/apache/fop/layoutmgr/TextLayoutManager.java b/src/org/apache/fop/layoutmgr/TextLayoutManager.java new file mode 100644 index 000000000..aa88340ab --- /dev/null +++ b/src/org/apache/fop/layoutmgr/TextLayoutManager.java @@ -0,0 +1,73 @@ +/* + * $Id$ + * Copyright (C) 2001 The Apache Software Foundation. All rights reserved. + * For details on use and redistribution please refer to the + * LICENSE file included with these sources. + */ + +package org.apache.fop.layoutmgr; + +import org.apache.fop.fo.FObj; +import org.apache.fop.area.Area; +import org.apache.fop.area.inline.Word; + +import java.util.ListIterator; + +/** + * LayoutManager for text (a sequence of characters) which generates one + * more inline areas. + */ +public class TextLayoutManager extends AbstractLayoutManager { + + private char[] chars; + private Word curWordArea; + + public TextLayoutManager(FObj fobj, char[] chars) { + super(fobj); + this.chars = chars; + } + + + /** + * Generate inline areas for words in text. + */ + public void generateAreas() { + // Iterate over characters and make text areas. + // Add each one to parent. Handle word-space. + curWordArea = new Word(); + curWordArea.setWord(new String(chars)); + flush(); + } + + + protected void flush() { + parentLM.addChild(curWordArea); + } + + + public boolean generatesInlineAreas() { + return true; + } + + /** + * This is a leaf-node, so this method is never called. + */ + public void addChild(Area childArea) {} + + + /** + * This is a leaf-node, so this method is never called. + */ + public Area getParentArea(Area childArea) { + return null; + } + + + + /** Try to split the word area by hyphenating the word. */ + public boolean splitArea(Area areaToSplit, SplitContext context) { + context.nextArea = areaToSplit; + return false; + } + +} -- 2.39.5