1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798991001011021031041051061071081091101111121131141151161171181191201211221231241251261271281291301311321331341351361371381391401411421431441451461471481491501511521531541551561571581591601611621631641651661671681691701711721731741751761771781791801811821831841851861871881891901911921931941951961971981992002012022032042052062072082092102112122132142152162172182192202212222232242252262272282292302312322332342352362372382392402412422432442452462472482492502512522532542552562572582592602612622632642652662672682692702712722732742752762772782792802812822832842852862872882892902912922932942952962972982993003013023033043053063073083093103113123133143153163173183193203213223233243253263273283293303313323333343353363373383393403413423433443453463473483493503513523533543553563573583593603613623633643653663673683693703713723733743753763773783793803813823833843853863873883893903913923933943953963973983994004014024034044054064074084094104114124134144154164174184194204214224234244254264274284294304314324334344354364374384394404414424434444454464474484494504514524534544554564574584594604614624634644654664674684694704714724734744754764774784794804814824834844854864874884894904914924934944954964974984995005015025035045055065075085095105115125135145155165175185195205215225235245255265275285295305315325335345355365375385395405415425435445455465475485495505515525535545555565575585595605615625635645655665675685695705715725735745755765775785795805815825835845855865875885895905915925935945955965975985996006016026036046056066076086096106116126136146156166176186196206216226236246256266276286296306316326336346356366376386396406416426436446456466476486496506516526536546556566576586596606616626636646656666676686696706716726736746756766776786796806816826836846856866876886896906916926936946956966976986997007017027037047057067077087097107117127137147157167177187197207217227237247257267277287297307317327337347357367377387397407417427437447457467477487497507517527537547557567577587597607617627637647657667677687697707717727737747757767777787797807817827837847857867877887897907917927937947957967977987998008018028038048058068078088098108118128138148158168178188198208218228238248258268278288298308318328338348358368378388398408418428438448458468478488498508518528538548558568578588598608618628638648658668678688698708718728738748758768778788798808818828838848858868878888898908918928938948958968978988999009019029039049059069079089099109119129139149159169179189199209219229239249259269279289299309319329339349359369379389399409419429439449459469479489499509519529539549559569579589599609619629639649659669679689699709719729739749759769779789799809819829839849859869879889899909919929939949959969979989991000100110021003100410051006100710081009101010111012101310141015101610171018101910201021102210231024102510261027102810291030103110321033103410351036103710381039104010411042104310441045104610471048104910501051105210531054105510561057105810591060106110621063106410651066106710681069107010711072107310741075107610771078107910801081108210831084108510861087108810891090109110921093109410951096109710981099110011011102110311041105110611071108110911101111111211131114111511161117111811191120112111221123112411251126112711281129113011311132113311341135113611371138113911401141114211431144114511461147114811491150115111521153115411551156115711581159116011611162116311641165116611671168116911701171117211731174117511761177117811791180118111821183118411851186118711881189119011911192119311941195119611971198119912001201120212031204120512061207120812091210121112121213121412151216121712181219122012211222122312241225122612271228122912301231123212331234123512361237123812391240124112421243124412451246124712481249125012511252125312541255125612571258125912601261126212631264126512661267126812691270127112721273127412751276127712781279128012811282128312841285128612871288128912901291129212931294129512961297129812991300130113021303130413051306130713081309131013111312131313141315131613171318131913201321132213231324132513261327132813291330133113321333133413351336133713381339134013411342134313441345134613471348134913501351135213531354135513561357135813591360136113621363136413651366136713681369137013711372137313741375137613771378137913801381138213831384138513861387138813891390139113921393139413951396139713981399140014011402140314041405140614071408140914101411141214131414141514161417141814191420142114221423142414251426142714281429143014311432143314341435143614371438143914401441144214431444144514461447144814491450145114521453145414551456145714581459146014611462146314641465146614671468146914701471147214731474147514761477147814791480148114821483148414851486148714881489 |
- /*
- * Copyright 1999-2005 The Apache Software Foundation.
- *
- * Licensed 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;
-
- import java.util.Iterator;
- import java.util.LinkedList;
- import java.util.List;
- import java.util.ListIterator;
-
- import org.apache.fop.area.Area;
- import org.apache.fop.area.BlockParent;
- import org.apache.fop.area.Block;
- import org.apache.fop.fo.FObj;
- import org.apache.fop.fo.properties.CommonBorderPaddingBackground;
- import org.apache.fop.fo.properties.SpaceProperty;
- import org.apache.fop.layoutmgr.inline.LineLayoutManager;
- import org.apache.fop.traits.MinOptMax;
-
- /**
- * Base LayoutManager class for all areas which stack their child
- * areas in the block-progression direction, such as Flow, Block, ListBlock.
- */
- public abstract class BlockStackingLayoutManager extends AbstractLayoutManager
- implements BlockLevelLayoutManager {
- /**
- * Reference to FO whose areas it's managing or to the traits
- * of the FO.
- */
- //protected LayoutManager curChildLM = null; AbstractLayoutManager also defines this!
- protected BlockParent parentArea = null;
-
- /** Value of the block-progression-unit (non-standard property) */
- protected int bpUnit = 0;
- /** space-before value adjusted for block-progression-unit handling */
- protected int adjustedSpaceBefore = 0;
- /** space-after value adjusted for block-progression-unit handling */
- protected int adjustedSpaceAfter = 0;
- /** Only used to store the original list when createUnitElements is called */
- protected LinkedList storedList = null;
- /** Indicates whether break before has been served or not */
- protected boolean bBreakBeforeServed = false;
- /** Indicates whether the first visible mark has been returned by this LM, yet */
- protected boolean firstVisibleMarkServed = false;
- /** Reference IPD available */
- protected int referenceIPD = 0;
- /**
- * Holds the (one-time use) fo:block space-before
- * and -after properties. Large fo:blocks are split
- * into multiple Area. Blocks to accomodate the subsequent
- * regions (pages) they are placed on. space-before
- * is applied at the beginning of the first
- * Block and space-after at the end of the last Block
- * used in rendering the fo:block.
- */
- protected MinOptMax foSpaceBefore = null;
- /** see foSpaceBefore */
- protected MinOptMax foSpaceAfter = null;
-
- private Position auxiliaryPosition;
-
- private int contentAreaIPD = 0;
-
- /**
- * @param node the fo this LM deals with
- */
- public BlockStackingLayoutManager(FObj node) {
- super(node);
- setGeneratesBlockArea(true);
- }
-
- /**
- * @return current area being filled
- */
- protected BlockParent getCurrentArea() {
- return this.parentArea;
- }
-
-
- /**
- * Set the current area being filled.
- * @param parentArea the current area to be filled
- */
- protected void setCurrentArea(BlockParent parentArea) {
- this.parentArea = parentArea;
- }
-
- /**
- * Add a block spacer for space before and space after a block.
- * This adds an empty Block area that acts as a block space.
- *
- * @param adjust the adjustment value
- * @param minoptmax the min/opt/max value of the spacing
- */
- public void addBlockSpacing(double adjust, MinOptMax minoptmax) {
- int sp = TraitSetter.getEffectiveSpace(adjust, minoptmax);
- if (sp != 0) {
- Block spacer = new Block();
- spacer.setBPD(sp);
- parentLM.addChildArea(spacer);
- }
- }
-
- /**
- * Add the childArea to the passed area.
- * Called by child LayoutManager when it has filled one of its areas.
- * The LM should already have an Area in which to put the child.
- * See if the area will fit in the current area.
- * If so, add it. Otherwise initiate breaking.
- * @param childArea the area to add: will be some block-stacked Area.
- * @param parentArea the area in which to add the childArea
- */
- protected void addChildToArea(Area childArea,
- BlockParent parentArea) {
- // This should be a block-level Area (Block in the generic sense)
- if (!(childArea instanceof Block)) {
- //log.error("Child not a Block in BlockStackingLM!");
- }
-
- parentArea.addBlock((Block) childArea);
- flush(); // hand off current area to parent
- }
-
-
- /**
- * Add the childArea to the current area.
- * Called by child LayoutManager when it has filled one of its areas.
- * The LM should already have an Area in which to put the child.
- * See if the area will fit in the current area.
- * If so, add it. Otherwise initiate breaking.
- * @param childArea the area to add: will be some block-stacked Area.
- */
- public void addChildArea(Area childArea) {
- addChildToArea(childArea, getCurrentArea());
- }
-
- /**
- * Force current area to be added to parent area.
- */
- protected void flush() {
- if (getCurrentArea() != null) {
- parentLM.addChildArea(getCurrentArea());
- }
- }
-
- /** @return a cached auxiliary Position instance used for things like spaces. */
- protected Position getAuxiliaryPosition() {
- if (this.auxiliaryPosition == null) {
- this.auxiliaryPosition = new NonLeafPosition(this, null);
- }
- return this.auxiliaryPosition;
- }
-
- /**
- * @param len length in millipoints to span with bp units
- * @return the minimum integer n such that n * bpUnit >= len
- */
- protected int neededUnits(int len) {
- return (int) Math.ceil((float)len / bpUnit);
- }
-
- /**
- * @see LayoutManager#getNextKnuthElements(LayoutContext, int)
- */
- public LinkedList getNextKnuthElements(LayoutContext context, int alignment) {
- /* LF *///System.err.println("BLM.getNextKnuthElements> keep-together = "
- // + layoutProps.keepTogether.getType());
- /* LF *///System.err.println(" keep-with-previous = " +
- // layoutProps.keepWithPrevious.getType());
- /* LF *///System.err.println(" keep-with-next = " +
- // layoutProps.keepWithNext.getType());
- BlockLevelLayoutManager curLM; // currently active LM
- BlockLevelLayoutManager prevLM = null; // previously active LM
-
- referenceIPD = context.getRefIPD();
-
- int iIndents = 0;
- int bIndents = 0;
- if (fobj instanceof org.apache.fop.fo.flow.Block) {
- org.apache.fop.fo.flow.Block block = (org.apache.fop.fo.flow.Block)fobj;
- iIndents = block.getCommonMarginBlock().startIndent.getValue(this)
- + block.getCommonMarginBlock().endIndent.getValue(this);
- bIndents = block.getCommonBorderPaddingBackground().getBPPaddingAndBorder(false, this);
- }
- int ipd = referenceIPD - iIndents;
-
- MinOptMax stackSize = new MinOptMax();
-
- // Set context for percentage property values.
- setContentAreaIPD(ipd);
-
- LinkedList returnedList = null;
- LinkedList contentList = new LinkedList();
- LinkedList returnList = new LinkedList();
-
- if (!bBreakBeforeServed) {
- try {
- if (addKnuthElementsForBreakBefore(returnList, context)) {
- return returnList;
- }
- } finally {
- bBreakBeforeServed = true;
- }
- }
-
- addKnuthElementsForSpaceBefore(returnList, alignment);
-
- addKnuthElementsForBorderPaddingBefore(returnList, !firstVisibleMarkServed);
- firstVisibleMarkServed = true;
-
- //Spaces, border and padding to be repeated at each break
- addPendingMarks(context);
-
- while ((curLM = (BlockLevelLayoutManager) getChildLM()) != null) {
- LayoutContext childLC = new LayoutContext(0);
- childLC.copyPendingMarksFrom(context);
- if (curLM instanceof LineLayoutManager) {
- // curLM is a LineLayoutManager
- // set stackLimit for lines
- childLC.setStackLimit(new MinOptMax(ipd/*
- * - iIndents -
- * iTextIndent
- */));
- childLC.setRefIPD(ipd);
- } else {
- // curLM is a ?
- //childLC.setStackLimit(MinOptMax.subtract(context
- // .getStackLimit(), stackSize));
- childLC.setStackLimit(context.getStackLimit());
- childLC.setRefIPD(referenceIPD);
- }
-
- // get elements from curLM
- returnedList = curLM.getNextKnuthElements(childLC, alignment);
- if (contentList.size() == 0 && childLC.isKeepWithPreviousPending()) {
- context.setFlags(LayoutContext.KEEP_WITH_PREVIOUS_PENDING);
- childLC.setFlags(LayoutContext.KEEP_WITH_PREVIOUS_PENDING, false);
- }
- if (returnedList != null
- && returnedList.size() == 1
- && ((ListElement) returnedList.getFirst()).isForcedBreak()) {
- // a descendant of this block has break-before
- /*
- if (returnList.size() == 0) {
- // the first child (or its first child ...) has
- // break-before;
- // all this block, including space before, will be put in
- // the
- // following page
- bSpaceBeforeServed = false;
- }*/
- contentList.addAll(returnedList);
-
- /* extension: conversione di tutta la sequenza fin'ora ottenuta */
- if (bpUnit > 0) {
- storedList = contentList;
- contentList = createUnitElements(contentList);
- }
- /* end of extension */
-
- // "wrap" the Position inside each element
- // moving the elements from contentList to returnList
- returnedList = new LinkedList();
- wrapPositionElements(contentList, returnList);
-
- return returnList;
- } else {
- if (prevLM != null) {
- // there is a block handled by prevLM
- // before the one handled by curLM
- if (mustKeepTogether()
- || context.isKeepWithNextPending()
- || childLC.isKeepWithPreviousPending()) {
- //Clear keep pending flag
- context.setFlags(LayoutContext.KEEP_WITH_NEXT_PENDING, false);
- childLC.setFlags(LayoutContext.KEEP_WITH_PREVIOUS_PENDING, false);
- // add an infinite penalty to forbid a break between
- // blocks
- contentList.add(new BreakElement(
- new Position(this), KnuthElement.INFINITE, context));
- /*
- contentList.add(new KnuthPenalty(0,
- KnuthElement.INFINITE, false,
- new Position(this), false));
- */
- } else if (!((ListElement) contentList.getLast()).isGlue()) {
- // add a null penalty to allow a break between blocks
- contentList.add(new BreakElement(
- new Position(this), 0, context));
- /*
- contentList.add(new KnuthPenalty(0, 0, false,
- new Position(this), false));*/
- } else {
- // the last element in contentList is a glue;
- // it is a feasible breakpoint, there is no need to add
- // a penalty
- log.warn("glue-type break possibility not handled properly, yet");
- //TODO Does this happen? If yes, need to deal with border and padding
- //at the break possibility
- }
- }
- if (returnedList == null || returnedList.size() == 0) {
- //Avoid NoSuchElementException below (happens with empty blocks)
- continue;
- }
- contentList.addAll(returnedList);
- if (((ListElement) returnedList.getLast()).isForcedBreak()) {
- // a descendant of this block has break-after
- if (curLM.isFinished()) {
- // there is no other content in this block;
- // it's useless to add space after before a page break
- setFinished(true);
- }
-
- /* extension: conversione di tutta la sequenza fin'ora ottenuta */
- if (bpUnit > 0) {
- storedList = contentList;
- contentList = createUnitElements(contentList);
- }
- /* end of extension */
-
- returnedList = new LinkedList();
- wrapPositionElements(contentList, returnList);
-
- return returnList;
- }
- /*
- if (allocatedSpace.min > context.getStackLimit().max) {
- log.debug("Allocated space exceeds stack limit, returning early.");
- return returnList;
- }*/
- }
- if (childLC.isKeepWithNextPending()) {
- //Clear and propagate
- childLC.setFlags(LayoutContext.KEEP_WITH_NEXT_PENDING, false);
- context.setFlags(LayoutContext.KEEP_WITH_NEXT_PENDING);
- }
- prevLM = curLM;
- }
-
- /* Extension: conversione di tutta la sequenza fin'ora ottenuta */
- if (bpUnit > 0) {
- storedList = contentList;
- contentList = createUnitElements(contentList);
- }
- /* end of extension */
-
- returnedList = new LinkedList();
- if (contentList.size() > 0) {
- wrapPositionElements(contentList, returnList);
- } else {
- //Empty fo:block, zero-length box makes sure the IDs are registered.
- returnList.add(new KnuthBox(0, notifyPos(new Position(this)), true));
- }
-
- addKnuthElementsForBorderPaddingAfter(returnList, true);
- addKnuthElementsForSpaceAfter(returnList, alignment);
- addKnuthElementsForBreakAfter(returnList, context);
-
- if (mustKeepWithNext()) {
- context.setFlags(LayoutContext.KEEP_WITH_NEXT_PENDING);
- }
- if (mustKeepWithPrevious()) {
- context.setFlags(LayoutContext.KEEP_WITH_PREVIOUS_PENDING);
- }
-
- setFinished(true);
-
- return returnList;
- }
-
- /**
- * @see org.apache.fop.layoutmgr.BlockLevelLayoutManager#negotiateBPDAdjustment(int, org.apache.fop.layoutmgr.KnuthElement)
- */
- public int negotiateBPDAdjustment(int adj, KnuthElement lastElement) {
- /*LF*/ //System.out.println(" BLM.negotiateBPDAdjustment> " + adj);
- /*LF*/ //System.out.println(" lastElement e' " + (lastElement.isPenalty()
- // ? "penalty" : (lastElement.isGlue() ? "glue" : "box" )));
- /*LF*/ //System.out.println(" position e' " + lastElement.getPosition().getClass().getName());
- /*LF*/ //System.out.println(" " + (bpUnit > 0 ? "unit" : ""));
- Position innerPosition = ((NonLeafPosition) lastElement.getPosition()).getPosition();
-
- if (innerPosition == null && lastElement.isGlue()) {
- // this adjustment applies to space-before or space-after of this block
- if (((KnuthGlue) lastElement).getAdjustmentClass() == SPACE_BEFORE_ADJUSTMENT) {
- // this adjustment applies to space-before
- adjustedSpaceBefore += adj;
- /*LF*/ //System.out.println(" BLM.negotiateBPDAdjustment> spazio prima: " + adj);
- } else {
- // this adjustment applies to space-after
- adjustedSpaceAfter += adj;
- /*LF*/ //System.out.println(" BLM.negotiateBPDAdjustment> spazio dopo: " + adj);
- }
- return adj;
- } else if (innerPosition instanceof MappingPosition) {
- // this block has block-progression-unit > 0: the adjustment can concern
- // - the space-before or space-after of this block,
- // - the line number of a descendant of this block
- MappingPosition mappingPos = (MappingPosition)innerPosition;
- if (lastElement.isGlue()) {
- // lastElement is a glue
- /*LF*/ //System.out.println(" BLM.negotiateBPDAdjustment> bpunit con glue");
- ListIterator storedListIterator = storedList.listIterator(
- mappingPos.getFirstIndex());
- int newAdjustment = 0;
- while (storedListIterator.nextIndex() <= mappingPos.getLastIndex()) {
- KnuthElement storedElement = (KnuthElement)storedListIterator.next();
- if (storedElement.isGlue()) {
- newAdjustment += ((BlockLevelLayoutManager)storedElement
- .getLayoutManager()).negotiateBPDAdjustment(
- adj - newAdjustment, storedElement);
- /*LF*/ //System.out.println(" BLM.negotiateBPDAdjustment> (progressivo) righe: "
- // + newAdjustment);
- }
- }
- newAdjustment = (newAdjustment > 0 ? bpUnit * neededUnits(newAdjustment)
- : -bpUnit * neededUnits(-newAdjustment));
- return newAdjustment;
- } else {
- // lastElement is a penalty: this means that the paragraph
- // has been split between consecutive pages:
- // this may involve a change in the number of lines
- /*LF*/ //System.out.println(" BLM.negotiateBPDAdjustment> bpunit con penalty");
- KnuthPenalty storedPenalty = (KnuthPenalty)
- storedList.get(mappingPos.getLastIndex());
- if (storedPenalty.getW() > 0) {
- // the original penalty has width > 0
- /*LF*/ //System.out.println(" BLM.negotiateBPDAdjustment> chiamata passata");
- return ((BlockLevelLayoutManager)storedPenalty.getLayoutManager())
- .negotiateBPDAdjustment(storedPenalty.getW(),
- (KnuthElement)storedPenalty);
- } else {
- // the original penalty has width = 0
- // the adjustment involves only the spaces before and after
- /*LF*/ //System.out.println(" BLM.negotiateBPDAdjustment> chiamata gestita");
- return adj;
- }
- }
- } else if (innerPosition.getLM() != this) {
- // this adjustment concerns another LM
- NonLeafPosition savedPos = (NonLeafPosition) lastElement.getPosition();
- lastElement.setPosition(innerPosition);
- int returnValue = ((BlockLevelLayoutManager)lastElement.getLayoutManager())
- .negotiateBPDAdjustment(adj, lastElement);
- lastElement.setPosition(savedPos);
- /*LF*/ //System.out.println(" BLM.negotiateBPDAdjustment> righe: " + returnValue);
- return returnValue;
- } else {
- // this should never happen
- log.error("BlockLayoutManager.negotiateBPDAdjustment(): unexpected Position");
- return 0;
- }
- }
-
- /**
- * @see BlockLevelLayoutManager#discardSpace(KnuthGlue)
- */
- public void discardSpace(KnuthGlue spaceGlue) {
- //System.out.println(" BLM.discardSpace> " + spaceGlue.getPosition().getClass().getName());
- Position innerPosition = ((NonLeafPosition) spaceGlue.getPosition()).getPosition();
-
- if (innerPosition == null || innerPosition.getLM() == this) {
- // if this block has block-progression-unit > 0, innerPosition can be
- // a MappingPosition
- // spaceGlue represents space before or space after of this block
- if (spaceGlue.getAdjustmentClass() == SPACE_BEFORE_ADJUSTMENT) {
- // space-before must be discarded
- adjustedSpaceBefore = 0;
- foSpaceBefore = new MinOptMax(0);
- } else {
- // space-after must be discarded
- adjustedSpaceAfter = 0;
- foSpaceAfter = new MinOptMax(0);
- //TODO Why are both cases handled in the same way?
- }
- } else {
- // this element was not created by this BlockLM
- NonLeafPosition savedPos = (NonLeafPosition)spaceGlue.getPosition();
- spaceGlue.setPosition(innerPosition);
- ((BlockLevelLayoutManager) spaceGlue.getLayoutManager()).discardSpace(spaceGlue);
- spaceGlue.setPosition(savedPos);
- }
- }
-
- /**
- * @see LayoutManager#getChangedKnuthElements(List, int)
- */
- public LinkedList getChangedKnuthElements(List oldList, int alignment) {
- /*LF*/ //System.out.println("");
- /*LF*/ //System.out.println(" BLM.getChangedKnuthElements> inizio: oldList.size() = "
- // + oldList.size());
- ListIterator oldListIterator = oldList.listIterator();
- KnuthElement returnedElement;
- KnuthElement currElement = null;
- KnuthElement prevElement = null;
- LinkedList returnedList = new LinkedList();
- LinkedList returnList = new LinkedList();
- int fromIndex = 0;
-
- // "unwrap" the Positions stored in the elements
- KnuthElement oldElement = null;
- while (oldListIterator.hasNext()) {
- oldElement = (KnuthElement)oldListIterator.next();
- Position innerPosition = ((NonLeafPosition) oldElement.getPosition()).getPosition();
- //System.out.println(" BLM> unwrapping: "
- // + (oldElement.isBox() ? "box " : (oldElement.isGlue() ? "glue " : "penalty"))
- // + " creato da " + oldElement.getLayoutManager().getClass().getName());
- //System.out.println(" BLM> unwrapping: "
- // + oldElement.getPosition().getClass().getName());
- if (innerPosition != null) {
- // oldElement was created by a descendant of this BlockLM
- oldElement.setPosition(innerPosition);
- } else {
- // thisElement was created by this BlockLM
- // modify its position in order to recognize it was not created
- // by a child
- oldElement.setPosition(new Position(this));
- }
- }
-
- // create the iterator
- List workList;
- if (bpUnit == 0) {
- workList = oldList;
- } else {
- // the storedList must be used instead of oldList;
- // find the index of the first element of returnedList
- // corresponding to the first element of oldList
- oldListIterator = oldList.listIterator();
- KnuthElement el = (KnuthElement) oldListIterator.next();
- while (!(el.getPosition() instanceof MappingPosition)) {
- el = (KnuthElement) oldListIterator.next();
- }
- int iFirst = ((MappingPosition) el.getPosition()).getFirstIndex();
-
- // find the index of the last element of returnedList
- // corresponding to the last element of oldList
- oldListIterator = oldList.listIterator(oldList.size());
- el = (KnuthElement) oldListIterator.previous();
- while (!(el.getPosition() instanceof MappingPosition)) {
- el = (KnuthElement) oldListIterator.previous();
- }
- int iLast = ((MappingPosition) el.getPosition()).getLastIndex();
-
- //System.out.println(" si usa storedList da " + iFirst + " a " + iLast
- // + " compresi su " + storedList.size() + " elementi totali");
- workList = storedList.subList(iFirst, iLast + 1);
- }
- ListIterator workListIterator = workList.listIterator();
-
- //System.out.println("");
- //System.out.println(" BLM.getChangedKnuthElements> workList.size() = "
- // + workList.size() + " da 0 a " + (workList.size() - 1));
-
- while (workListIterator.hasNext()) {
- currElement = (KnuthElement) workListIterator.next();
- //System.out.println("elemento n. " + workListIterator.previousIndex()
- // + " nella workList");
- if (prevElement != null
- && prevElement.getLayoutManager() != currElement.getLayoutManager()) {
- // prevElement is the last element generated by the same LM
- BlockLevelLayoutManager prevLM = (BlockLevelLayoutManager)
- prevElement.getLayoutManager();
- BlockLevelLayoutManager currLM = (BlockLevelLayoutManager)
- currElement.getLayoutManager();
- boolean bSomethingAdded = false;
- if (prevLM != this) {
- //System.out.println(" BLM.getChangedKnuthElements> chiamata da "
- // + fromIndex + " a " + workListIterator.previousIndex() + " su "
- // + prevLM.getClass().getName());
- returnedList.addAll(prevLM.getChangedKnuthElements(workList.subList(
- fromIndex, workListIterator.previousIndex()), alignment));
- bSomethingAdded = true;
- } else {
- // prevLM == this
- // do nothing
- //System.out.println(" BLM.getChangedKnuthElements> elementi propri, "
- // + "ignorati, da " + fromIndex + " a " + workListIterator.previousIndex()
- // + " su " + prevLM.getClass().getName());
- }
- fromIndex = workListIterator.previousIndex();
-
- // there is another block after this one
- if (bSomethingAdded
- && (this.mustKeepTogether()
- || prevLM.mustKeepWithNext()
- || currLM.mustKeepWithPrevious())) {
- // add an infinite penalty to forbid a break between blocks
- returnedList.add(new KnuthPenalty(0, KnuthElement.INFINITE, false,
- new Position(this), false));
- } else if (bSomethingAdded && !((KnuthElement) returnedList.getLast()).isGlue()) {
- // add a null penalty to allow a break between blocks
- returnedList.add(new KnuthPenalty(0, 0, false, new Position(this), false));
- }
- }
- prevElement = currElement;
- }
- if (currElement != null) {
- BlockLevelLayoutManager currLM = (BlockLevelLayoutManager)
- currElement.getLayoutManager();
- if (currLM != this) {
- //System.out.println(" BLM.getChangedKnuthElements> chiamata da " + fromIndex
- // + " a " + oldList.size() + " su " + currLM.getClass().getName());
- returnedList.addAll(currLM.getChangedKnuthElements(
- workList.subList(fromIndex, workList.size()), alignment));
- } else {
- // currLM == this
- // there are no more elements to add
- // remove the last penalty added to returnedList
- if (returnedList.size() > 0) {
- returnedList.removeLast();
- }
- //System.out.println(" BLM.getChangedKnuthElements> elementi propri, ignorati, da "
- // + fromIndex + " a " + workList.size());
- }
- }
-
- // append elements representing space-before
- boolean spaceBeforeIsConditional = true;
- if (fobj instanceof org.apache.fop.fo.flow.Block) {
- spaceBeforeIsConditional = ((org.apache.fop.fo.flow.Block)fobj)
- .getCommonMarginBlock().spaceBefore.getSpace().isDiscard();
- }
- if (bpUnit > 0
- || adjustedSpaceBefore != 0) {
- if (!spaceBeforeIsConditional) {
- // add elements to prevent the glue to be discarded
- returnList.add(new KnuthBox(0,
- new NonLeafPosition(this, null), false));
- returnList.add(new KnuthPenalty(0, KnuthElement.INFINITE, false,
- new NonLeafPosition(this, null), false));
- }
- if (bpUnit > 0) {
- returnList.add(new KnuthGlue(0, 0, 0,
- SPACE_BEFORE_ADJUSTMENT, new NonLeafPosition(this, null), true));
- } else {
- returnList.add(new KnuthGlue(adjustedSpaceBefore, 0, 0,
- SPACE_BEFORE_ADJUSTMENT, new NonLeafPosition(this, null), true));
- }
- }
-
- //System.out.println(" BLM.getChangedKnuthElements> intermedio: returnedList.size() = "
- // + returnedList.size());
-
- /* estensione: conversione complessiva */
- /*LF*/ if (bpUnit > 0) {
- /*LF*/ storedList = returnedList;
- /*LF*/ returnedList = createUnitElements(returnedList);
- /*LF*/ }
- /* estensione */
-
- // "wrap" the Position stored in each element of returnedList
- // and add elements to returnList
- ListIterator listIter = returnedList.listIterator();
- while (listIter.hasNext()) {
- returnedElement = (KnuthElement)listIter.next();
- returnedElement.setPosition(new NonLeafPosition(this, returnedElement.getPosition()));
- returnList.add(returnedElement);
- }
-
- // append elements representing space-after
- boolean spaceAfterIsConditional = true;
- if (fobj instanceof org.apache.fop.fo.flow.Block) {
- spaceAfterIsConditional = ((org.apache.fop.fo.flow.Block)fobj)
- .getCommonMarginBlock().spaceAfter.getSpace().isDiscard();
- }
- if (bpUnit > 0 || adjustedSpaceAfter != 0) {
- if (!spaceAfterIsConditional) {
- returnList.add(new KnuthPenalty(0,
- KnuthElement.INFINITE, false,
- new NonLeafPosition(this, null), false));
- }
- if (bpUnit > 0) {
- returnList.add(new KnuthGlue(0, 0, 0,
- SPACE_AFTER_ADJUSTMENT,
- new NonLeafPosition(this, null),
- (!spaceAfterIsConditional) ? false : true));
- } else {
- returnList.add(new KnuthGlue(adjustedSpaceAfter, 0, 0,
- SPACE_AFTER_ADJUSTMENT,
- new NonLeafPosition(this, null),
- (!spaceAfterIsConditional) ? false : true));
- }
- if (!spaceAfterIsConditional) {
- returnList.add(new KnuthBox(0,
- new NonLeafPosition(this, null), true));
- }
- }
-
- //System.out.println(" BLM.getChangedKnuthElements> finished: returnList.size() = "
- // + returnList.size());
- return returnList;
- }
-
- /**
- * @see org.apache.fop.layoutmgr.BlockLevelLayoutManager#mustKeepTogether()
- */
- public boolean mustKeepTogether() {
- return false;
- }
-
- /**
- * @see org.apache.fop.layoutmgr.BlockLevelLayoutManager#mustKeepWithPrevious()
- */
- public boolean mustKeepWithPrevious() {
- return false;
- }
-
- /**
- * @see org.apache.fop.layoutmgr.BlockLevelLayoutManager#mustKeepWithNext()
- */
- public boolean mustKeepWithNext() {
- return false;
- }
-
- /**
- * Adds the unresolved elements for border and padding to a layout context so break
- * possibilities can be properly constructed.
- * @param context the layout context
- */
- protected void addPendingMarks(LayoutContext context) {
- SpaceProperty spaceBefore = getSpaceBeforeProperty();
- if (spaceBefore != null
- && !(spaceBefore.getMinimum(this).getLength().getValue(this) == 0
- && spaceBefore.getMaximum(this).getLength().getValue(this) == 0)) {
- context.addPendingBeforeMark(new SpaceElement(getAuxiliaryPosition(), spaceBefore,
- RelSide.BEFORE,
- true, false, this));
- }
- SpaceProperty spaceAfter = getSpaceAfterProperty();
- if (spaceAfter != null
- && !(spaceAfter.getMinimum(this).getLength().getValue(this) == 0
- && spaceAfter.getMaximum(this).getLength().getValue(this) == 0)) {
- context.addPendingAfterMark(new SpaceElement(getAuxiliaryPosition(), spaceAfter,
- RelSide.AFTER,
- false, true, this));
- }
- CommonBorderPaddingBackground borderAndPadding = getBorderPaddingBackground();
- if (borderAndPadding != null) {
- if (borderAndPadding.getBorderBeforeWidth(false) > 0) {
- context.addPendingBeforeMark(new BorderElement(
- getAuxiliaryPosition(),
- borderAndPadding.getBorderInfo(
- CommonBorderPaddingBackground.BEFORE).getWidth(),
- RelSide.BEFORE,
- false, false, this));
- }
- if (borderAndPadding.getPaddingBefore(false, this) > 0) {
- context.addPendingBeforeMark(new PaddingElement(
- getAuxiliaryPosition(),
- borderAndPadding.getPaddingLengthProperty(
- CommonBorderPaddingBackground.BEFORE),
- RelSide.BEFORE,
- false, false, this));
- }
- if (borderAndPadding.getBorderAfterWidth(false) > 0) {
- context.addPendingAfterMark(new BorderElement(
- getAuxiliaryPosition(),
- borderAndPadding.getBorderInfo(
- CommonBorderPaddingBackground.AFTER).getWidth(),
- RelSide.AFTER,
- false, false, this));
- }
- if (borderAndPadding.getPaddingAfter(false, this) > 0) {
- context.addPendingAfterMark(new PaddingElement(
- getAuxiliaryPosition(),
- borderAndPadding.getPaddingLengthProperty(
- CommonBorderPaddingBackground.AFTER),
- RelSide.AFTER,
- false, false, this));
- }
- }
- }
-
- /** @return the border, padding and background info structure */
- private CommonBorderPaddingBackground getBorderPaddingBackground() {
- if (fobj instanceof org.apache.fop.fo.flow.Block) {
- return ((org.apache.fop.fo.flow.Block)fobj)
- .getCommonBorderPaddingBackground();
- } else if (fobj instanceof org.apache.fop.fo.flow.BlockContainer) {
- return ((org.apache.fop.fo.flow.BlockContainer)fobj)
- .getCommonBorderPaddingBackground();
- } else if (fobj instanceof org.apache.fop.fo.flow.ListBlock) {
- return ((org.apache.fop.fo.flow.ListBlock)fobj)
- .getCommonBorderPaddingBackground();
- } else if (fobj instanceof org.apache.fop.fo.flow.ListItem) {
- return ((org.apache.fop.fo.flow.ListItem)fobj)
- .getCommonBorderPaddingBackground();
- } else if (fobj instanceof org.apache.fop.fo.flow.Table) {
- return ((org.apache.fop.fo.flow.Table)fobj)
- .getCommonBorderPaddingBackground();
- } else {
- return null;
- }
- }
-
- /** @return the space-before property */
- private SpaceProperty getSpaceBeforeProperty() {
- if (fobj instanceof org.apache.fop.fo.flow.Block) {
- return ((org.apache.fop.fo.flow.Block)fobj)
- .getCommonMarginBlock().spaceBefore;
- } else if (fobj instanceof org.apache.fop.fo.flow.BlockContainer) {
- return ((org.apache.fop.fo.flow.BlockContainer)fobj)
- .getCommonMarginBlock().spaceBefore;
- } else if (fobj instanceof org.apache.fop.fo.flow.ListBlock) {
- return ((org.apache.fop.fo.flow.ListBlock)fobj)
- .getCommonMarginBlock().spaceBefore;
- } else if (fobj instanceof org.apache.fop.fo.flow.ListItem) {
- return ((org.apache.fop.fo.flow.ListItem)fobj)
- .getCommonMarginBlock().spaceBefore;
- } else if (fobj instanceof org.apache.fop.fo.flow.Table) {
- return ((org.apache.fop.fo.flow.Table)fobj)
- .getCommonMarginBlock().spaceBefore;
- } else {
- return null;
- }
- }
-
- /** @return the space-after property */
- private SpaceProperty getSpaceAfterProperty() {
- if (fobj instanceof org.apache.fop.fo.flow.Block) {
- return ((org.apache.fop.fo.flow.Block)fobj)
- .getCommonMarginBlock().spaceAfter;
- } else if (fobj instanceof org.apache.fop.fo.flow.BlockContainer) {
- return ((org.apache.fop.fo.flow.BlockContainer)fobj)
- .getCommonMarginBlock().spaceAfter;
- } else if (fobj instanceof org.apache.fop.fo.flow.ListBlock) {
- return ((org.apache.fop.fo.flow.ListBlock)fobj)
- .getCommonMarginBlock().spaceAfter;
- } else if (fobj instanceof org.apache.fop.fo.flow.ListItem) {
- return ((org.apache.fop.fo.flow.ListItem)fobj)
- .getCommonMarginBlock().spaceAfter;
- } else if (fobj instanceof org.apache.fop.fo.flow.Table) {
- return ((org.apache.fop.fo.flow.Table)fobj)
- .getCommonMarginBlock().spaceAfter;
- } else {
- return null;
- }
- }
-
- /**
- * Creates Knuth elements for before border padding and adds them to the return list.
- * @param returnList return list to add the additional elements to
- */
- protected void addKnuthElementsForBorderPaddingBefore(LinkedList returnList, boolean isFirst) {
- //Border and Padding (before)
- CommonBorderPaddingBackground borderAndPadding = getBorderPaddingBackground();
- if (borderAndPadding != null) {
- if (borderAndPadding.getBorderBeforeWidth(false) > 0) {
- returnList.add(new BorderElement(
- getAuxiliaryPosition(),
- borderAndPadding.getBorderInfo(CommonBorderPaddingBackground.BEFORE)
- .getWidth(),
- RelSide.BEFORE, isFirst, false, this));
- }
- if (borderAndPadding.getPaddingBefore(false, this) > 0) {
- returnList.add(new PaddingElement(
- getAuxiliaryPosition(),
- borderAndPadding.getPaddingLengthProperty(
- CommonBorderPaddingBackground.BEFORE),
- RelSide.BEFORE, isFirst, false, this));
- }
- //TODO Handle conditionality
- /*
- int bpBefore = borderAndPadding.getBorderBeforeWidth(false)
- + borderAndPadding.getPaddingBefore(false, this);
- if (bpBefore > 0) {
- returnList.add(new KnuthBox(bpBefore, getAuxiliaryPosition(), true));
- }*/
- }
- }
-
- /**
- * Creates Knuth elements for after border padding and adds them to the return list.
- * @param returnList return list to add the additional elements to
- */
- protected void addKnuthElementsForBorderPaddingAfter(LinkedList returnList, boolean isLast) {
- //Border and Padding (after)
- CommonBorderPaddingBackground borderAndPadding = getBorderPaddingBackground();
- if (borderAndPadding != null) {
- if (borderAndPadding.getPaddingAfter(false, this) > 0) {
- returnList.add(new PaddingElement(
- getAuxiliaryPosition(),
- borderAndPadding.getPaddingLengthProperty(
- CommonBorderPaddingBackground.AFTER),
- RelSide.AFTER, false, isLast, this));
- }
- if (borderAndPadding.getBorderAfterWidth(false) > 0) {
- returnList.add(new BorderElement(
- getAuxiliaryPosition(),
- borderAndPadding.getBorderInfo(CommonBorderPaddingBackground.AFTER)
- .getWidth(),
- RelSide.AFTER, false, isLast, this));
- }
- //TODO Handle conditionality
- /*
- int bpAfter = borderAndPadding.getBorderAfterWidth(false)
- + borderAndPadding.getPaddingAfter(false, this);
- if (bpAfter > 0) {
- returnList.add(new KnuthBox(bpAfter, getAuxiliaryPosition(), true));
- }*/
- }
- }
-
- /**
- * Creates Knuth elements for break-before and adds them to the return list.
- * @param returnList return list to add the additional elements to
- * @return true if an element has been added due to a break-before.
- */
- protected boolean addKnuthElementsForBreakBefore(LinkedList returnList,
- LayoutContext context) {
- int breakBefore = -1;
- if (fobj instanceof org.apache.fop.fo.flow.Block) {
- breakBefore = ((org.apache.fop.fo.flow.Block) fobj).getBreakBefore();
- } else if (fobj instanceof org.apache.fop.fo.flow.BlockContainer) {
- breakBefore = ((org.apache.fop.fo.flow.BlockContainer) fobj).getBreakBefore();
- } else if (fobj instanceof org.apache.fop.fo.flow.Table) {
- breakBefore = ((org.apache.fop.fo.flow.Table) fobj).getBreakBefore();
- }
- if (breakBefore == EN_PAGE
- || breakBefore == EN_COLUMN
- || breakBefore == EN_EVEN_PAGE
- || breakBefore == EN_ODD_PAGE) {
- // return a penalty element, representing a forced page break
- returnList.add(new BreakElement(getAuxiliaryPosition(),
- 0, -KnuthElement.INFINITE, breakBefore, context));
- //returnList.add(new KnuthPenalty(0, -KnuthElement.INFINITE, false,
- // breakBefore, getAuxiliaryPosition(), false));
- return true;
- } else {
- return false;
- }
- }
-
- /**
- * Creates Knuth elements for break-after and adds them to the return list.
- * @param returnList return list to add the additional elements to
- * @return true if an element has been added due to a break-after.
- */
- protected boolean addKnuthElementsForBreakAfter(LinkedList returnList,
- LayoutContext context) {
- int breakAfter = -1;
- if (fobj instanceof org.apache.fop.fo.flow.Block) {
- breakAfter = ((org.apache.fop.fo.flow.Block) fobj).getBreakAfter();
- } else if (fobj instanceof org.apache.fop.fo.flow.BlockContainer) {
- breakAfter = ((org.apache.fop.fo.flow.BlockContainer) fobj).getBreakAfter();
- } else if (fobj instanceof org.apache.fop.fo.flow.Table) {
- breakAfter = ((org.apache.fop.fo.flow.Table) fobj).getBreakAfter();
- }
- if (breakAfter == EN_PAGE
- || breakAfter == EN_COLUMN
- || breakAfter == EN_EVEN_PAGE
- || breakAfter == EN_ODD_PAGE) {
- // add a penalty element, representing a forced page break
- returnList.add(new BreakElement(getAuxiliaryPosition(),
- 0, -KnuthElement.INFINITE, breakAfter, context));
- //returnList.add(new KnuthPenalty(0, -KnuthElement.INFINITE, false,
- // breakAfter, getAuxiliaryPosition(), false));
- return true;
- } else {
- return false;
- }
- }
-
- /**
- * Creates Knuth elements for space-before and adds them to the return list.
- * @param returnList return list to add the additional elements to
- * @param alignment vertical alignment
- */
- protected void addKnuthElementsForSpaceBefore(LinkedList returnList/*,
- Position returnPosition*/, int alignment) {
- SpaceProperty spaceBefore = getSpaceBeforeProperty();
- // append elements representing space-before
- if (spaceBefore != null
- && !(spaceBefore.getMinimum(this).getLength().getValue(this) == 0
- && spaceBefore.getMaximum(this).getLength().getValue(this) == 0)) {
- returnList.add(new SpaceElement(getAuxiliaryPosition(), spaceBefore,
- RelSide.BEFORE,
- true, false, this));
- }
- /*
- if (bpUnit > 0
- || spaceBefore != null
- && !(spaceBefore.getMinimum(this).getLength().getValue(this) == 0
- && spaceBefore.getMaximum(this).getLength().getValue(this) == 0)) {
- if (spaceBefore != null && !spaceBefore.getSpace().isDiscard()) {
- // add elements to prevent the glue to be discarded
- returnList.add(new KnuthBox(0, getAuxiliaryPosition(), false));
- returnList.add(new KnuthPenalty(0, KnuthElement.INFINITE,
- false, getAuxiliaryPosition(), false));
- }
- if (bpUnit > 0) {
- returnList.add(new KnuthGlue(0, 0, 0,
- BlockLevelLayoutManager.SPACE_BEFORE_ADJUSTMENT,
- getAuxiliaryPosition(), true));
- } else { //if (alignment == EN_JUSTIFY) {
- returnList.add(new KnuthGlue(
- spaceBefore.getOptimum(this).getLength().getValue(this),
- spaceBefore.getMaximum(this).getLength().getValue(this)
- - spaceBefore.getOptimum(this).getLength().getValue(this),
- spaceBefore.getOptimum(this).getLength().getValue(this)
- - spaceBefore.getMinimum(this).getLength().getValue(this),
- BlockLevelLayoutManager.SPACE_BEFORE_ADJUSTMENT,
- getAuxiliaryPosition(), true));
- // } else {
- // returnList.add(new KnuthGlue(
- // spaceBefore.getOptimum().getLength().getValue(this),
- // 0, 0, BlockLevelLayoutManager.SPACE_BEFORE_ADJUSTMENT,
- // returnPosition, true));
- }
- }*/
- }
-
- /**
- * Creates Knuth elements for space-after and adds them to the return list.
- * @param returnList return list to add the additional elements to
- * @param alignment vertical alignment
- */
- protected void addKnuthElementsForSpaceAfter(LinkedList returnList/*, Position returnPosition*/,
- int alignment) {
- SpaceProperty spaceAfter = getSpaceAfterProperty();
- // append elements representing space-after
- if (spaceAfter != null
- && !(spaceAfter.getMinimum(this).getLength().getValue(this) == 0
- && spaceAfter.getMaximum(this).getLength().getValue(this) == 0)) {
- returnList.add(new SpaceElement(getAuxiliaryPosition(), spaceAfter,
- RelSide.AFTER,
- false, true, this));
- }
- /*
- if (bpUnit > 0
- || spaceAfter != null
- && !(spaceAfter.getMinimum(this).getLength().getValue(this) == 0
- && spaceAfter.getMaximum(this).getLength().getValue(this) == 0)) {
- if (spaceAfter != null && !spaceAfter.getSpace().isDiscard()) {
- returnList.add(new KnuthPenalty(0, KnuthElement.INFINITE,
- false, getAuxiliaryPosition(), false));
- }
- if (bpUnit > 0) {
- returnList.add(new KnuthGlue(0, 0, 0,
- BlockLevelLayoutManager.SPACE_AFTER_ADJUSTMENT,
- getAuxiliaryPosition(), true));
- } else { //if (alignment == EN_JUSTIFY) {
- returnList.add(new KnuthGlue(
- spaceAfter.getOptimum(this).getLength().getValue(this),
- spaceAfter.getMaximum(this).getLength().getValue(this)
- - spaceAfter.getOptimum(this).getLength().getValue(this),
- spaceAfter.getOptimum(this).getLength().getValue(this)
- - spaceAfter.getMinimum(this).getLength().getValue(this),
- BlockLevelLayoutManager.SPACE_AFTER_ADJUSTMENT, getAuxiliaryPosition(),
- (!spaceAfter.getSpace().isDiscard()) ? false : true));
- // } else {
- // returnList.add(new KnuthGlue(
- // spaceAfter.getOptimum().getLength().getValue(this), 0, 0,
- // BlockLevelLayoutManager.SPACE_AFTER_ADJUSTMENT, returnPosition,
- // (!spaceAfter.getSpace().isDiscard()) ? false : true));
- }
- if (spaceAfter != null && !spaceAfter.getSpace().isDiscard()) {
- returnList.add(new KnuthBox(0, getAuxiliaryPosition(), true));
- }
- }*/
- }
-
- protected LinkedList createUnitElements(LinkedList oldList) {
- //System.out.println(" ");
- //System.out.println("Start conversion: " + oldList.size()
- // + " elements, space-before.min=" + layoutProps.spaceBefore.getSpace().min
- // + " space-after.min=" + layoutProps.spaceAfter.getSpace().min);
- // add elements at the beginning and at the end of oldList
- // representing minimum spaces
- LayoutManager lm = ((KnuthElement)oldList.getFirst()).getLayoutManager();
- boolean bAddedBoxBefore = false;
- boolean bAddedBoxAfter = false;
- if (adjustedSpaceBefore > 0) {
- oldList.addFirst(new KnuthBox(adjustedSpaceBefore,
- new Position(lm), true));
- bAddedBoxBefore = true;
- }
- if (adjustedSpaceAfter > 0) {
- oldList.addLast(new KnuthBox(adjustedSpaceAfter,
- new Position(lm), true));
- bAddedBoxAfter = true;
- }
-
- MinOptMax totalLength = new MinOptMax(0);
- MinOptMax totalUnits = new MinOptMax(0);
- LinkedList newList = new LinkedList();
-
- //System.out.println(" ");
- //System.out.println(" Prima scansione");
- // scan the list once to compute total min, opt and max length
- ListIterator oldListIterator = oldList.listIterator();
- while (oldListIterator.hasNext()) {
- KnuthElement element = (KnuthElement) oldListIterator.next();
- if (element.isBox()) {
- totalLength.add(new MinOptMax(element.getW()));
- //System.out.println("box " + element.getW());
- } else if (element.isGlue()) {
- totalLength.min -= ((KnuthGlue) element).getZ();
- totalLength.max += ((KnuthGlue) element).getY();
- //leafValue = ((LeafPosition) element.getPosition()).getLeafPos();
- //System.out.println("glue " + element.getW() + " + "
- // + ((KnuthGlue) element).getY() + " - " + ((KnuthGlue) element).getZ());
- } else {
- //System.out.println((((KnuthPenalty)element).getP() == KnuthElement.INFINITE
- // ? "PENALTY " : "penalty ") + element.getW());
- }
- }
- // compute the total amount of "units"
- totalUnits = new MinOptMax(neededUnits(totalLength.min),
- neededUnits(totalLength.opt),
- neededUnits(totalLength.max));
- //System.out.println(" totalLength= " + totalLength);
- //System.out.println(" unita'= " + totalUnits);
-
- //System.out.println(" ");
- //System.out.println(" Seconda scansione");
- // scan the list once more, stopping at every breaking point
- // in order to compute partial min, opt and max length
- // and create the new elements
- oldListIterator = oldList.listIterator();
- boolean bPrevIsBox = false;
- MinOptMax lengthBeforeBreak = new MinOptMax(0);
- MinOptMax lengthAfterBreak = (MinOptMax) totalLength.clone();
- MinOptMax unitsBeforeBreak;
- MinOptMax unitsAfterBreak;
- MinOptMax unsuppressibleUnits = new MinOptMax(0);
- int firstIndex = 0;
- int lastIndex = -1;
- while (oldListIterator.hasNext()) {
- KnuthElement element = (KnuthElement) oldListIterator.next();
- lastIndex++;
- if (element.isBox()) {
- lengthBeforeBreak.add(new MinOptMax(element.getW()));
- lengthAfterBreak.subtract(new MinOptMax(element.getW()));
- bPrevIsBox = true;
- } else if (element.isGlue()) {
- lengthBeforeBreak.min -= ((KnuthGlue) element).getZ();
- lengthAfterBreak.min += ((KnuthGlue) element).getZ();
- lengthBeforeBreak.max += ((KnuthGlue) element).getY();
- lengthAfterBreak.max -= ((KnuthGlue) element).getY();
- bPrevIsBox = false;
- } else {
- lengthBeforeBreak.add(new MinOptMax(element.getW()));
- bPrevIsBox = false;
- }
-
- // create the new elements
- if (element.isPenalty() && ((KnuthPenalty) element).getP() < KnuthElement.INFINITE
- || element.isGlue() && bPrevIsBox
- || !oldListIterator.hasNext()) {
- // suppress elements after the breaking point
- int iStepsForward = 0;
- while (oldListIterator.hasNext()) {
- KnuthElement el = (KnuthElement) oldListIterator.next();
- iStepsForward++;
- if (el.isGlue()) {
- // suppressed glue
- lengthAfterBreak.min += ((KnuthGlue) el).getZ();
- lengthAfterBreak.max -= ((KnuthGlue) el).getY();
- } else if (el.isPenalty()) {
- // suppressed penalty, do nothing
- } else {
- // box, end of suppressions
- break;
- }
- }
- // compute the partial amount of "units" before and after the break
- unitsBeforeBreak = new MinOptMax(neededUnits(lengthBeforeBreak.min),
- neededUnits(lengthBeforeBreak.opt),
- neededUnits(lengthBeforeBreak.max));
- unitsAfterBreak = new MinOptMax(neededUnits(lengthAfterBreak.min),
- neededUnits(lengthAfterBreak.opt),
- neededUnits(lengthAfterBreak.max));
-
- // rewind the iterator and lengthAfterBreak
- for (int i = 0; i < iStepsForward; i++) {
- KnuthElement el = (KnuthElement) oldListIterator.previous();
- if (el.isGlue()) {
- lengthAfterBreak.min -= ((KnuthGlue) el).getZ();
- lengthAfterBreak.max += ((KnuthGlue) el).getY();
- }
- }
-
- // compute changes in length, stretch and shrink
- int uLengthChange = unitsBeforeBreak.opt + unitsAfterBreak.opt - totalUnits.opt;
- int uStretchChange = (unitsBeforeBreak.max + unitsAfterBreak.max - totalUnits.max)
- - (unitsBeforeBreak.opt + unitsAfterBreak.opt - totalUnits.opt);
- int uShrinkChange = (unitsBeforeBreak.opt + unitsAfterBreak.opt - totalUnits.opt)
- - (unitsBeforeBreak.min + unitsAfterBreak.min - totalUnits.min);
-
- // compute the number of normal, stretch and shrink unit
- // that must be added to the new sequence
- int uNewNormal = unitsBeforeBreak.opt - unsuppressibleUnits.opt;
- int uNewStretch = (unitsBeforeBreak.max - unitsBeforeBreak.opt)
- - (unsuppressibleUnits.max - unsuppressibleUnits.opt);
- int uNewShrink = (unitsBeforeBreak.opt - unitsBeforeBreak.min)
- - (unsuppressibleUnits.opt - unsuppressibleUnits.min);
-
- //System.out.println("("
- // + unsuppressibleUnits.min + "-" + unsuppressibleUnits.opt + "-"
- // + unsuppressibleUnits.max + ") "
- // + " -> " + unitsBeforeBreak.min + "-" + unitsBeforeBreak.opt + "-"
- // + unitsBeforeBreak.max
- // + " + " + unitsAfterBreak.min + "-" + unitsAfterBreak.opt + "-"
- // + unitsAfterBreak.max
- // + (uLengthChange != 0 ? " [length " + uLengthChange + "] " : "")
- // + (uStretchChange != 0 ? " [stretch " + uStretchChange + "] " : "")
- // + (uShrinkChange != 0 ? " [shrink " + uShrinkChange + "]" : ""));
-
- // create the MappingPosition which will be stored in the new elements
- // correct firstIndex and lastIndex
- int firstIndexCorrection = 0;
- int lastIndexCorrection = 0;
- if (bAddedBoxBefore) {
- if (firstIndex != 0) {
- firstIndexCorrection++;
- }
- lastIndexCorrection++;
- }
- if (bAddedBoxAfter && lastIndex == (oldList.size() - 1)) {
- lastIndexCorrection++;
- }
- MappingPosition mappingPos = new MappingPosition(this,
- firstIndex - firstIndexCorrection,
- lastIndex - lastIndexCorrection);
-
- // new box
- newList.add(new KnuthBox((uNewNormal - uLengthChange) * bpUnit,
- mappingPos,
- false));
- unsuppressibleUnits.add(new MinOptMax(uNewNormal - uLengthChange));
- //System.out.println(" box " + (uNewNormal - uLengthChange));
-
- // new infinite penalty, glue and box, if necessary
- if (uNewStretch - uStretchChange > 0
- || uNewShrink - uShrinkChange > 0) {
- int iStretchUnits = (uNewStretch - uStretchChange > 0
- ? (uNewStretch - uStretchChange) : 0);
- int iShrinkUnits = (uNewShrink - uShrinkChange > 0
- ? (uNewShrink - uShrinkChange) : 0);
- newList.add(new KnuthPenalty(0, KnuthElement.INFINITE, false,
- mappingPos,
- false));
- newList.add(new KnuthGlue(0,
- iStretchUnits * bpUnit,
- iShrinkUnits * bpUnit,
- LINE_NUMBER_ADJUSTMENT,
- mappingPos,
- false));
- //System.out.println(" PENALTY");
- //System.out.println(" glue 0 " + iStretchUnits + " " + iShrinkUnits);
- unsuppressibleUnits.max += iStretchUnits;
- unsuppressibleUnits.min -= iShrinkUnits;
- if (!oldListIterator.hasNext()) {
- newList.add(new KnuthBox(0,
- mappingPos,
- false));
- //System.out.println(" box 0");
- }
- }
-
- // new breaking sequence
- if (uStretchChange != 0
- || uShrinkChange != 0) {
- // new infinite penalty, glue, penalty and glue
- newList.add(new KnuthPenalty(0, KnuthElement.INFINITE, false,
- mappingPos,
- false));
- newList.add(new KnuthGlue(0,
- uStretchChange * bpUnit,
- uShrinkChange * bpUnit,
- LINE_NUMBER_ADJUSTMENT,
- mappingPos,
- false));
- newList.add(new KnuthPenalty(uLengthChange * bpUnit,
- 0, false, element.getPosition(), false));
- newList.add(new KnuthGlue(0,
- -uStretchChange * bpUnit,
- -uShrinkChange * bpUnit,
- LINE_NUMBER_ADJUSTMENT,
- mappingPos,
- false));
- //System.out.println(" PENALTY");
- //System.out.println(" glue 0 " + uStretchChange + " " + uShrinkChange);
- //System.out.println(" penalty " + uLengthChange + " * unit");
- //System.out.println(" glue 0 " + (- uStretchChange) + " "
- // + (- uShrinkChange));
- } else if (oldListIterator.hasNext()) {
- // new penalty
- newList.add(new KnuthPenalty(uLengthChange * bpUnit,
- 0, false,
- mappingPos,
- false));
- //System.out.println(" penalty " + uLengthChange + " * unit");
- }
- // update firstIndex
- firstIndex = lastIndex + 1;
- }
-
- if (element.isPenalty()) {
- lengthBeforeBreak.add(new MinOptMax(-element.getW()));
- }
-
- }
-
- // remove elements at the beginning and at the end of oldList
- // representing minimum spaces
- if (adjustedSpaceBefore > 0) {
- oldList.removeFirst();
- }
- if (adjustedSpaceAfter > 0) {
- oldList.removeLast();
- }
-
- // if space-before.conditionality is "discard", correct newList
- boolean correctFirstElement = false;
- if (fobj instanceof org.apache.fop.fo.flow.Block) {
- correctFirstElement = ((org.apache.fop.fo.flow.Block)fobj)
- .getCommonMarginBlock().spaceBefore.getSpace().isDiscard();
- }
- if (correctFirstElement) {
- // remove the wrong element
- KnuthBox wrongBox = (KnuthBox) newList.removeFirst();
- // if this paragraph is at the top of a page, the space before
- // must be ignored; compute the length change
- int decreasedLength = (neededUnits(totalLength.opt)
- - neededUnits(totalLength.opt - adjustedSpaceBefore))
- * bpUnit;
- // insert the correct elements
- newList.addFirst(new KnuthBox(wrongBox.getW() - decreasedLength,
- wrongBox.getPosition(), false));
- newList.addFirst(new KnuthGlue(decreasedLength, 0, 0, SPACE_BEFORE_ADJUSTMENT,
- wrongBox.getPosition(), false));
- //System.out.println(" rimosso box " + neededUnits(wrongBox.getW()));
- //System.out.println(" aggiunto glue " + neededUnits(decreasedLength) + " 0 0");
- //System.out.println(" aggiunto box " + neededUnits(
- // wrongBox.getW() - decreasedLength));
- }
-
- // if space-after.conditionality is "discard", correct newList
- boolean correctLastElement = false;
- if (fobj instanceof org.apache.fop.fo.flow.Block) {
- correctLastElement = ((org.apache.fop.fo.flow.Block)fobj)
- .getCommonMarginBlock().spaceAfter.getSpace().isDiscard();
- }
- if (correctLastElement) {
- // remove the wrong element
- KnuthBox wrongBox = (KnuthBox) newList.removeLast();
- // if the old sequence is box(h) penalty(inf) glue(x,y,z) box(0)
- // (it cannot be parted and has some stretch or shrink)
- // the wrong box is the first one, not the last one
- LinkedList preserveList = new LinkedList();
- if (wrongBox.getW() == 0) {
- preserveList.add(wrongBox);
- preserveList.addFirst((KnuthGlue) newList.removeLast());
- preserveList.addFirst((KnuthPenalty) newList.removeLast());
- wrongBox = (KnuthBox) newList.removeLast();
- }
-
- // if this paragraph is at the bottom of a page, the space after
- // must be ignored; compute the length change
- int decreasedLength = (neededUnits(totalLength.opt)
- - neededUnits(totalLength.opt - adjustedSpaceAfter))
- * bpUnit;
- // insert the correct box
- newList.addLast(new KnuthBox(wrongBox.getW() - decreasedLength,
- wrongBox.getPosition(), false));
- // add preserved elements
- if (preserveList.size() > 0) {
- newList.addAll(preserveList);
- }
- // insert the correct glue
- newList.addLast(new KnuthGlue(decreasedLength, 0, 0, SPACE_AFTER_ADJUSTMENT,
- wrongBox.getPosition(), false));
- //System.out.println(" rimosso box " + neededUnits(wrongBox.getW()));
- //System.out.println(" aggiunto box " + neededUnits(
- // wrongBox.getW() - decreasedLength));
- //System.out.println(" aggiunto glue " + neededUnits(decreasedLength) + " 0 0");
- }
-
- return newList;
- }
-
- protected static class StackingIter extends PositionIterator {
- StackingIter(Iterator parentIter) {
- super(parentIter);
- }
-
- protected LayoutManager getLM(Object nextObj) {
- return ((Position) nextObj).getLM();
- }
-
- protected Position getPos(Object nextObj) {
- return ((Position) nextObj);
- }
- }
-
- protected static class MappingPosition extends Position {
- private int iFirstIndex;
- private int iLastIndex;
-
- public MappingPosition(LayoutManager lm, int first, int last) {
- super(lm);
- iFirstIndex = first;
- iLastIndex = last;
- }
-
- public int getFirstIndex() {
- return iFirstIndex;
- }
-
- public int getLastIndex() {
- return iLastIndex;
- }
- }
-
- /**
- * "wrap" the Position inside each element moving the elements from
- * SourceList to targetList
- * @param sourceList source list
- * @param targetList target list receiving the wrapped position elements
- */
- protected void wrapPositionElements(List sourceList, List targetList) {
- wrapPositionElements(sourceList, targetList, false);
- }
-
- /**
- * "wrap" the Position inside each element moving the elements from
- * SourceList to targetList
- * @param sourceList source list
- * @param targetList target list receiving the wrapped position elements
- * @param force if true, every Position is wrapper regardless of its LM of origin
- */
- protected void wrapPositionElements(List sourceList, List targetList, boolean force) {
-
- ListIterator listIter = sourceList.listIterator();
- while (listIter.hasNext()) {
- ListElement tempElement;
- tempElement = (ListElement) listIter.next();
- if (force || tempElement.getLayoutManager() != this) {
- tempElement.setPosition(notifyPos(new NonLeafPosition(this,
- tempElement.getPosition())));
- }
- targetList.add(tempElement);
- }
- }
-
- /**
- * Returns the IPD of the content area
- * @return the IPD of the content area
- */
- public int getContentAreaIPD() {
- return contentAreaIPD;
- }
-
- /**
- * Sets the IPD of the content area
- * @param contentAreaIPD the IPD of the content area
- */
- protected void setContentAreaIPD(int contentAreaIPD) {
- this.contentAreaIPD = contentAreaIPD;
- }
-
- /**
- * Returns the BPD of the content area
- * @return the BPD of the content area
- */
- public int getContentAreaBPD() {
- return -1;
- }
-
- }
|