Package org.apache.fop.layoutmgr.inline

Source Code of org.apache.fop.layoutmgr.inline.InlineStackingLayoutManager$StackingIter

/*
* 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: InlineStackingLayoutManager.java 426576 2006-07-28 15:44:37Z jeremias $ */

package org.apache.fop.layoutmgr.inline;

import java.util.LinkedList;
import java.util.Iterator;
import java.util.List;
import java.util.ListIterator;
import java.util.HashMap;

import org.apache.fop.fo.FObj;
import org.apache.fop.fo.properties.SpaceProperty;
import org.apache.fop.layoutmgr.AbstractLayoutManager;
import org.apache.fop.layoutmgr.KnuthElement;
import org.apache.fop.layoutmgr.LayoutContext;
import org.apache.fop.layoutmgr.LayoutManager;
import org.apache.fop.layoutmgr.NonLeafPosition;
import org.apache.fop.layoutmgr.Position;
import org.apache.fop.layoutmgr.PositionIterator;
import org.apache.fop.area.Area;
import org.apache.fop.area.inline.Space;
import org.apache.fop.traits.MinOptMax;

/**
* Class modelling the commonalities of layoutmanagers for objects
* which stack children in the inline direction, such as Inline or
* Line. It should not be instantiated directly.
*/
public class InlineStackingLayoutManager extends AbstractLayoutManager
                                         implements InlineLevelLayoutManager {


    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);
        }
    }


    /**
     * Size of any start or end borders and padding.
     */
    private MinOptMax allocIPD = new MinOptMax(0);

    /**
     * Size of border and padding in BPD (ie, before and after).
     */
    protected MinOptMax extraBPD;

    private Area currentArea; // LineArea or InlineParent

    //private BreakPoss prevBP;
   
    /** The child layout context */
    protected LayoutContext childLC;

    private boolean bAreaCreated = false;

    //private LayoutManager currentLM = null;

    /** Used to store previous content IPD for each child LM. */
    private HashMap hmPrevIPD = new HashMap();

    /**
     * Create an inline stacking layout manager.
     * This is used for fo's that create areas that
     * contain inline areas.
     *
     * @param node the formatting object that creates the area
     */
    protected InlineStackingLayoutManager(FObj node) {
        super(node);
        extraBPD = new MinOptMax(0);
    }

    /**
     * Set the iterator.
     *
     * @param iter the iterator for this LM
     */
    public void setLMiter(ListIterator iter) {
        childLMiter = iter;
    }

    /**
     * Returns the extra IPD needed for any leading or trailing fences for the
     * current area.
     * @param bNotFirst true if not the first area for this layout manager
     * @param bNotLast true if not the last area for this layout manager
     * @return the extra IPD as a MinOptMax spec
     */
    protected MinOptMax getExtraIPD(boolean bNotFirst, boolean bNotLast) {
        return new MinOptMax(0);
    }


    /**
     * Indication if the current area has a leading fence.
     * @param bNotFirst true if not the first area for this layout manager
     * @return the leading fence flag
     */
    protected boolean hasLeadingFence(boolean bNotFirst) {
        return false;
    }

    /**
     * Indication if the current area has a trailing fence.
     * @param bNotLast true if not the last area for this layout manager
     * @return the trailing fence flag
     */
    protected boolean hasTrailingFence(boolean bNotLast) {
        return false;
    }

    /**
     * Get the space at the start of the inline area.
     * @return the space property describing the space
     */
    protected SpaceProperty getSpaceStart() {
        return null;
    }
   
    /**
     * Get the space at the end of the inline area.
     * @return the space property describing the space
     */
    protected SpaceProperty getSpaceEnd() {
        return null;
    }

    /**
     * Reset position for returning next BreakPossibility.
     * @param prevPos a Position returned by this layout manager
     * representing a potential break decision.
     */
    public void resetPosition(Position prevPos) {
        if (prevPos != null) {
            // ASSERT (prevPos.getLM() == this)
            if (prevPos.getLM() != this) {
                //getLogger().error(
                //  "InlineStackingLayoutManager.resetPosition: " +
                //  "LM mismatch!!!");
            }
            // Back up the child LM Position
            Position childPos = prevPos.getPosition();
            reset(childPos);
            /*
            if (prevBP != null
                    && prevBP.getLayoutManager() != childPos.getLM()) {
                childLC = null;
            }
            prevBP = new BreakPoss(childPos);
            */
        } else {
            // Backup to start of first child layout manager
            //prevBP = null;
            // super.resetPosition(prevPos);
            reset(prevPos);
            // If any areas created, we are restarting!
            bAreaCreated = false;
        }
        // Do we need to reset some context like pending or prevContent?
        // What about prevBP?
    }

    /**
     * TODO: Explain this method
     * @param lm ???
     * @return ???
     */
    protected MinOptMax getPrevIPD(LayoutManager lm) {
        return (MinOptMax) hmPrevIPD.get(lm);
    }

    /**
     * Clear the previous IPD calculation.
     */
    protected void clearPrevIPD() {
        hmPrevIPD.clear();
    }

    /**
     * This method is called by addAreas() so IDs can be added to a page for FOs that
     * support the 'id' property.
     */
    protected void addId() {
        // Do nothing here, overriden in subclasses that have an 'id' property.
    }
   
    /**
     * Returns the current area.
     * @return the current area
     */
    protected Area getCurrentArea() {
        return currentArea;
    }

    /**
     * Set the current area.
     * @param area the current area
     */
    protected void setCurrentArea(Area area) {
        currentArea = area;
    }

    /**
     * Trait setter to be overridden by subclasses.
     * @param bNotFirst true if this is not the first child area added
     * @param bNotLast true if this is not the last child area added
     */
    protected void setTraits(boolean bNotFirst, boolean bNotLast) {
    }

    /**
     * Set the current child layout context
     * @param lc the child layout context
     */
    protected void setChildContext(LayoutContext lc) {
        childLC = lc;
    }

    /**
     * Current child layout context
     * @return the current child layout context
     */
    protected LayoutContext getContext() {
        return childLC;
    }

    /**
     * Adds a space to the area
     * @param parentArea the area to which to add the space
     * @param spaceRange the space range specifier
     * @param dSpaceAdjust the factor by which to stretch or shrink the space
     */
    protected void addSpace(Area parentArea, MinOptMax spaceRange,
                            double dSpaceAdjust) {
        if (spaceRange != null) {
            int iAdjust = spaceRange.opt;
            if (dSpaceAdjust > 0.0) {
                // Stretch by factor
                iAdjust += (int) ((double) (spaceRange.max
                                          - spaceRange.opt) * dSpaceAdjust);
            } else if (dSpaceAdjust < 0.0) {
                // Shrink by factor
                iAdjust += (int) ((double) (spaceRange.opt
                                          - spaceRange.min) * dSpaceAdjust);
            }
            if (iAdjust != 0) {
                //getLogger().debug("Add leading space: " + iAdjust);
                Space ls = new Space();
                ls.setIPD(iAdjust);
                parentArea.addChildArea(ls);
            }
        }
    }

    /** @see InlineLevelLayoutManager#addALetterSpaceTo(List) */
    public List addALetterSpaceTo(List oldList) {
        // old list contains only a box, or the sequence: box penalty glue box

        ListIterator oldListIterator = oldList.listIterator();
        KnuthElement element = null;
        // "unwrap" the Position stored in each element of oldList
        while (oldListIterator.hasNext()) {
            element = (KnuthElement) oldListIterator.next();
            element.setPosition(((NonLeafPosition)element.getPosition()).getPosition());
        }

        // The last element may not have a layout manager (its position == null);
        // this may happen if it is a padding box; see bug 39571.
        InlineLevelLayoutManager LM =
            (InlineLevelLayoutManager) element.getLayoutManager();
        if (LM != null) {
            oldList = LM.addALetterSpaceTo(oldList);
        }
        // "wrap" again the Position stored in each element of oldList
        oldListIterator = oldList.listIterator();
        while (oldListIterator.hasNext()) {
            element = (KnuthElement) oldListIterator.next();
            element.setPosition(notifyPos(new NonLeafPosition(this, element.getPosition())));
        }

        return oldList;
    }

    /**
     * remove the AreaInfo object represented by the given elements,
     * so that it won't generate any element when getChangedKnuthElements
     * will be called
     *
     * @param oldList the elements representing the word space
     */
    public void removeWordSpace(List oldList) {
        ListIterator oldListIterator = oldList.listIterator();
        KnuthElement element = null;
        // "unwrap" the Position stored in each element of oldList
        while (oldListIterator.hasNext()) {
            element = (KnuthElement) oldListIterator.next();
            element.setPosition(((NonLeafPosition)element.getPosition()).getPosition());
        }

        ((InlineLevelLayoutManager)
                   element.getLayoutManager()).removeWordSpace(oldList);

    }

    /** @see InlineLevelLayoutManager#getWordChars(StringBuffer, Position) */
    public void getWordChars(StringBuffer sbChars, Position pos) {
        Position newPos = ((NonLeafPosition) pos).getPosition();
        ((InlineLevelLayoutManager)
         newPos.getLM()).getWordChars(sbChars, newPos);
    }

    /** @see InlineLevelLayoutManager#hyphenate(Position, HyphContext) */
    public void hyphenate(Position pos, HyphContext hc) {
        Position newPos = ((NonLeafPosition) pos).getPosition();
        ((InlineLevelLayoutManager)
         newPos.getLM()).hyphenate(newPos, hc);
    }

    /** @see InlineLevelLayoutManager#applyChanges(List) */
    public boolean applyChanges(List oldList) {
        // "unwrap" the Positions stored in the elements
        ListIterator oldListIterator = oldList.listIterator();
        KnuthElement oldElement;
        while (oldListIterator.hasNext()) {
            oldElement = (KnuthElement) oldListIterator.next();
            oldElement.setPosition
                (((NonLeafPosition) oldElement.getPosition()).getPosition());
        }
        // reset the iterator
        oldListIterator = oldList.listIterator();

        InlineLevelLayoutManager prevLM = null;
        InlineLevelLayoutManager currLM;
        int fromIndex = 0;

        boolean bSomethingChanged = false;
        while (oldListIterator.hasNext()) {
            oldElement = (KnuthElement) oldListIterator.next();
            currLM = (InlineLevelLayoutManager) oldElement.getLayoutManager();
            // initialize prevLM
            if (prevLM == null) {
                prevLM = currLM;
            }

            if (currLM != prevLM || !oldListIterator.hasNext()) {
                if (prevLM == this || currLM == this) {
                    prevLM = currLM;
                } else if (oldListIterator.hasNext()) {
                    bSomethingChanged
                        = prevLM.applyChanges(oldList.subList(fromIndex
                                                              , oldListIterator.previousIndex()))
                        || bSomethingChanged;
                    prevLM = currLM;
                    fromIndex = oldListIterator.previousIndex();
                } else if (currLM == prevLM) {
                    bSomethingChanged
                        = prevLM.applyChanges(oldList.subList(fromIndex, oldList.size()))
                            || bSomethingChanged;
                } else {
                    bSomethingChanged
                        = prevLM.applyChanges(oldList.subList(fromIndex
                                                              , oldListIterator.previousIndex()))
                            || bSomethingChanged;
                    if (currLM != null) {
                        bSomethingChanged
                            = currLM.applyChanges(oldList.subList(oldListIterator.previousIndex()
                                                                  , oldList.size()))
                            || bSomethingChanged;
                    }
                }
            }
        }

        // "wrap" again the Positions stored in the elements
        oldListIterator = oldList.listIterator();
        while (oldListIterator.hasNext()) {
            oldElement = (KnuthElement) oldListIterator.next();
            oldElement.setPosition
                (notifyPos(new NonLeafPosition(this, oldElement.getPosition())));
        }
        return bSomethingChanged;
    }

    /**
     * @see org.apache.fop.layoutmgr.LayoutManager#getChangedKnuthElements(List, int)
     */
    public LinkedList getChangedKnuthElements(List oldList, int alignment) {
        // "unwrap" the Positions stored in the elements
        ListIterator oldListIterator = oldList.listIterator();
        KnuthElement oldElement;
        while (oldListIterator.hasNext()) {
            oldElement = (KnuthElement) oldListIterator.next();
            oldElement.setPosition
                (((NonLeafPosition) oldElement.getPosition()).getPosition());
        }
        // reset the iterator
        oldListIterator = oldList.listIterator();

        KnuthElement returnedElement;
        LinkedList returnedList = new LinkedList();
        LinkedList returnList = new LinkedList();
        InlineLevelLayoutManager prevLM = null;
        InlineLevelLayoutManager currLM;
        int fromIndex = 0;

        while (oldListIterator.hasNext()) {
            oldElement = (KnuthElement) oldListIterator.next();
            currLM = (InlineLevelLayoutManager) oldElement.getLayoutManager();
            if (prevLM == null) {
                prevLM = currLM;
            }

            if (currLM != prevLM || !oldListIterator.hasNext()) {
                if (oldListIterator.hasNext()) {
                    returnedList.addAll
                        (prevLM.getChangedKnuthElements
                         (oldList.subList(fromIndex,
                                          oldListIterator.previousIndex()),
                          /*flaggedPenalty,*/ alignment));
                    prevLM = currLM;
                    fromIndex = oldListIterator.previousIndex();
                } else if (currLM == prevLM) {
                    returnedList.addAll
                        (prevLM.getChangedKnuthElements
                         (oldList.subList(fromIndex, oldList.size()),
                          /*flaggedPenalty,*/ alignment));
                } else {
                    returnedList.addAll
                        (prevLM.getChangedKnuthElements
                         (oldList.subList(fromIndex,
                                          oldListIterator.previousIndex()),
                          /*flaggedPenalty,*/ alignment));
                    if (currLM != null) {
                        returnedList.addAll
                            (currLM.getChangedKnuthElements
                             (oldList.subList(oldListIterator.previousIndex(),
                                              oldList.size()),
                              /*flaggedPenalty,*/ alignment));
                    }
                }
            }
        }

        // "wrap" the Position stored in each element of returnedList
        ListIterator listIter = returnedList.listIterator();
        while (listIter.hasNext()) {
            returnedElement = (KnuthElement) listIter.next();
            returnedElement.setPosition
                (notifyPos(new NonLeafPosition(this, returnedElement.getPosition())));
            returnList.add(returnedElement);
        }
        return returnList;
    }
}
TOP

Related Classes of org.apache.fop.layoutmgr.inline.InlineStackingLayoutManager$StackingIter

TOP
Copyright © 2018 www.massapi.com. All rights reserved.
All source code are property of their respective owners. Java is a trademark of Sun Microsystems, Inc and owned by ORACLE Inc. Contact coftware#gmail.com.