123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373 |
- /*
- * Licensed to the Apache Software Foundation (ASF) under one or more
- * contributor license agreements. See the NOTICE file distributed with
- * this work for additional information regarding copyright ownership.
- * The ASF licenses this file to You under the Apache License, Version 2.0
- * (the "License"); you may not use this file except in compliance with
- * the License. You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
- /* $Id$ */
-
- package org.apache.fop.layoutmgr.inline;
-
- import java.util.Collections;
- import java.util.LinkedList;
- import java.util.List;
-
- import org.apache.fop.area.Trait;
- import org.apache.fop.area.inline.FilledArea;
- import org.apache.fop.area.inline.InlineArea;
- import org.apache.fop.area.inline.Space;
- import org.apache.fop.area.inline.TextArea;
- import org.apache.fop.fo.FObj;
- import org.apache.fop.fo.flow.Leader;
- import org.apache.fop.fonts.Font;
- import org.apache.fop.fonts.FontInfo;
- import org.apache.fop.fonts.FontTriplet;
- import org.apache.fop.layoutmgr.InlineKnuthSequence;
- import org.apache.fop.layoutmgr.KnuthElement;
- import org.apache.fop.layoutmgr.KnuthGlue;
- import org.apache.fop.layoutmgr.KnuthPenalty;
- import org.apache.fop.layoutmgr.KnuthPossPosIter;
- import org.apache.fop.layoutmgr.KnuthSequence;
- import org.apache.fop.layoutmgr.LayoutContext;
- import org.apache.fop.layoutmgr.LeafPosition;
- import org.apache.fop.layoutmgr.Position;
- import org.apache.fop.layoutmgr.PositionIterator;
- import org.apache.fop.layoutmgr.TraitSetter;
- import org.apache.fop.traits.MinOptMax;
-
- /**
- * LayoutManager for the fo:leader formatting object
- */
- public class LeaderLayoutManager extends LeafNodeLayoutManager {
- private Leader fobj;
- private Font font;
-
- private List contentList;
- private ContentLayoutManager clm;
-
- private int contentAreaIPD;
-
- /**
- * Constructor
- *
- * @param node the formatting object that creates this area
- */
- public LeaderLayoutManager(Leader node) {
- super(node);
- fobj = node;
- }
-
- /** {@inheritDoc} */
- public void initialize() {
- FontInfo fi = fobj.getFOEventHandler().getFontInfo();
- FontTriplet[] fontkeys = fobj.getCommonFont().getFontState(fi);
- font = fi.getFontInstance(fontkeys[0], fobj.getCommonFont().fontSize.getValue(this));
- // the property leader-alignment does not affect vertical positioning
- // (see section 7.21.1 in the XSL Recommendation)
- // setAlignment(node.getLeaderAlignment());
- setCommonBorderPaddingBackground(fobj.getCommonBorderPaddingBackground());
- }
-
- /**
- * Return the inline area for this leader.
- * @param context the layout context
- * @return the inline area
- */
- public InlineArea get(LayoutContext context) {
- return getLeaderInlineArea(context);
- }
-
- /**
- * Return the allocated IPD for this area.
- * @param refIPD the IPD of the reference area
- * @return the allocated IPD
- */
- protected MinOptMax getAllocationIPD(int refIPD) {
- return getLeaderAllocIPD(refIPD);
- }
-
- private MinOptMax getLeaderAllocIPD(int ipd) {
- // length of the leader
- int borderPaddingWidth = 0;
- if (commonBorderPaddingBackground != null) {
- borderPaddingWidth = commonBorderPaddingBackground.getIPPaddingAndBorder(false, this);
- }
- setContentAreaIPD(ipd - borderPaddingWidth);
- int opt = fobj.getLeaderLength().getOptimum(this).getLength().getValue(this)
- - borderPaddingWidth;
- int min = fobj.getLeaderLength().getMinimum(this).getLength().getValue(this)
- - borderPaddingWidth;
- int max = fobj.getLeaderLength().getMaximum(this).getLength().getValue(this)
- - borderPaddingWidth;
- return MinOptMax.getInstance(min, opt, max);
- }
-
- private InlineArea getLeaderInlineArea(LayoutContext context) {
- InlineArea leaderArea = null;
- int level = fobj.getBidiLevel();
- if (fobj.getLeaderPattern() == EN_RULE) {
- if (fobj.getRuleStyle() != EN_NONE) {
- org.apache.fop.area.inline.Leader leader
- = new org.apache.fop.area.inline.Leader();
- leader.setRuleStyle(fobj.getRuleStyle());
- leader.setRuleThickness(fobj.getRuleThickness().getValue(this));
- leaderArea = leader;
- } else {
- leaderArea = new Space();
- if (level >= 0) {
- leaderArea.setBidiLevel(level);
- }
- }
- leaderArea.setBPD(fobj.getRuleThickness().getValue(this));
- leaderArea.addTrait(Trait.COLOR, fobj.getColor());
- if (level >= 0) {
- leaderArea.setBidiLevel(level);
- }
- } else if (fobj.getLeaderPattern() == EN_SPACE) {
- leaderArea = new Space();
- leaderArea.setBPD(fobj.getRuleThickness().getValue(this));
- if (level >= 0) {
- leaderArea.setBidiLevel(level);
- }
- } else if (fobj.getLeaderPattern() == EN_DOTS) {
- TextArea t = new TextArea();
- char dot = '.'; // userAgent.getLeaderDotCharacter();
- int width = font.getCharWidth(dot);
- int[] levels = (level < 0) ? null : new int[] {level};
- t.addWord("" + dot, width, null, levels, null, 0);
- t.setIPD(width);
- t.setBPD(width);
- t.setBaselineOffset(width);
- TraitSetter.addFontTraits(t, font);
- t.addTrait(Trait.COLOR, fobj.getColor());
- Space spacer = null;
- int widthLeaderPattern = fobj.getLeaderPatternWidth().getValue(this);
- if (widthLeaderPattern > width) {
- spacer = new Space();
- spacer.setIPD(widthLeaderPattern - width);
- if (level >= 0) {
- spacer.setBidiLevel(level);
- }
- width = widthLeaderPattern;
- }
- FilledArea fa = new FilledArea();
- fa.setUnitWidth(width);
- fa.addChildArea(t);
- if (spacer != null) {
- fa.addChildArea(spacer);
- }
- fa.setBPD(t.getBPD());
- leaderArea = fa;
- } else if (fobj.getLeaderPattern() == EN_USECONTENT) {
- if (fobj.getChildNodes() == null) {
- InlineLevelEventProducer eventProducer = InlineLevelEventProducer.Provider.get(
- getFObj().getUserAgent().getEventBroadcaster());
- eventProducer.leaderWithoutContent(this, getFObj().getLocator());
- return null;
- }
-
- // child FOs are assigned to the InlineStackingLM
- fobjIter = null;
-
- // get breaks then add areas to FilledArea
- FilledArea fa = new FilledArea();
-
- clm = new ContentLayoutManager(fa, this);
- addChildLM(clm);
-
- InlineLayoutManager lm;
- lm = new InlineLayoutManager(fobj);
- clm.addChildLM(lm);
- lm.initialize();
-
- LayoutContext childContext = LayoutContext.newInstance();
- childContext.setAlignmentContext(context.getAlignmentContext());
- contentList = clm.getNextKnuthElements(childContext, 0);
- int width = clm.getStackingSize();
- if (width != 0) {
- Space spacer = null;
- if (fobj.getLeaderPatternWidth().getValue(this) > width) {
- spacer = new Space();
- spacer.setIPD(fobj.getLeaderPatternWidth().getValue(this) - width);
- if (level >= 0) {
- spacer.setBidiLevel(level);
- }
- width = fobj.getLeaderPatternWidth().getValue(this);
- }
- fa.setUnitWidth(width);
- if (spacer != null) {
- fa.addChildArea(spacer);
- }
- leaderArea = fa;
- } else {
- //Content collapsed to nothing, so use a space
- leaderArea = new Space();
- leaderArea.setBPD(fobj.getRuleThickness().getValue(this));
- leaderArea.setBidiLevel(fobj.getBidiLevelRecursive());
- }
- }
-
- assert leaderArea != null;
- leaderArea.setChangeBarList(getChangeBarList());
-
- TraitSetter.setProducerID(leaderArea, fobj.getId());
- return leaderArea;
- }
-
- /** {@inheritDoc} */
- public void addAreas(PositionIterator posIter, LayoutContext context) {
- if (fobj.getLeaderPattern() != EN_USECONTENT) {
- // use LeafNodeLayoutManager.addAreas()
- super.addAreas(posIter, context);
- } else {
- addId();
-
- widthAdjustArea(curArea, context);
-
- if (commonBorderPaddingBackground != null) {
- // Add border and padding to area
- TraitSetter.setBorderPaddingTraits(curArea,
- commonBorderPaddingBackground,
- false, false, this);
- TraitSetter.addBackground(curArea, commonBorderPaddingBackground, this);
- }
-
- // add content areas
- KnuthPossPosIter contentIter = new KnuthPossPosIter(contentList, 0, contentList.size());
- clm.addAreas(contentIter, context);
-
- parentLayoutManager.addChildArea(curArea);
-
- while (posIter.hasNext()) {
- posIter.next();
- }
- }
- }
-
- /** {@inheritDoc} */
- public List getNextKnuthElements(LayoutContext context, int alignment) {
- MinOptMax ipd;
- curArea = get(context);
- KnuthSequence seq = new InlineKnuthSequence();
-
- if (curArea == null) {
- setFinished(true);
- return null;
- }
-
- alignmentContext = new AlignmentContext(curArea.getBPD()
- , fobj.getAlignmentAdjust()
- , fobj.getAlignmentBaseline()
- , fobj.getBaselineShift()
- , fobj.getDominantBaseline()
- , context.getAlignmentContext());
-
- ipd = getAllocationIPD(context.getRefIPD());
- if (fobj.getLeaderPattern() == EN_USECONTENT && curArea instanceof FilledArea) {
- // If we have user supplied content make it fit if we can
- int unitWidth = ((FilledArea) curArea).getUnitWidth();
- if (ipd.getOpt() < unitWidth && unitWidth <= ipd.getMax()) {
- ipd = MinOptMax.getInstance(ipd.getMin(), unitWidth, ipd.getMax());
- }
- }
-
- // create the AreaInfo object to store the computed values
- areaInfo = new AreaInfo((short) 0, ipd, false, context.getAlignmentContext());
- curArea.setAdjustingInfo(ipd.getStretch(), ipd.getShrink(), 0);
-
- addKnuthElementsForBorderPaddingStart(seq);
-
- // node is a fo:Leader
- seq.add(new KnuthInlineBox(0, alignmentContext, new LeafPosition(this, -1), true));
- seq.add(new KnuthPenalty(0, KnuthElement.INFINITE, false,
- new LeafPosition(this, -1), true));
- if (alignment == EN_JUSTIFY || alignment == 0) {
- seq.add(new KnuthGlue(areaInfo.ipdArea, new LeafPosition(this, 0), false));
- } else {
- seq.add(new KnuthGlue(areaInfo.ipdArea.getOpt(), 0, 0,
- new LeafPosition(this, 0), false));
- }
- seq.add(new KnuthInlineBox(0, alignmentContext, new LeafPosition(this, -1), true));
-
- addKnuthElementsForBorderPaddingEnd(seq);
-
- setFinished(true);
- return Collections.singletonList(seq);
- }
-
- /** {@inheritDoc} */
- public void hyphenate(Position pos, HyphContext hc) {
- // use the AbstractLayoutManager.hyphenate() null implementation
- super.hyphenate(pos, hc);
- }
-
- /** {@inheritDoc} */
- public boolean applyChanges(List oldList) {
- setFinished(false);
- return false;
- }
-
- /** {@inheritDoc} */
- public List getChangedKnuthElements(List oldList, int alignment) {
- if (isFinished()) {
- return null;
- }
-
- List returnList = new LinkedList();
-
- addKnuthElementsForBorderPaddingStart(returnList);
-
- returnList.add(new KnuthInlineBox(0, areaInfo.alignmentContext,
- new LeafPosition(this, -1), true));
- returnList.add(new KnuthPenalty(0, KnuthElement.INFINITE, false,
- new LeafPosition(this, -1), true));
- if (alignment == EN_JUSTIFY || alignment == 0) {
- returnList.add(new KnuthGlue(areaInfo.ipdArea, new LeafPosition(this, 0), false));
- } else {
- returnList.add(new KnuthGlue(areaInfo.ipdArea.getOpt(), 0, 0,
- new LeafPosition(this, 0), false));
- }
- returnList.add(new KnuthInlineBox(0, areaInfo.alignmentContext,
- new LeafPosition(this, -1), true));
-
- addKnuthElementsForBorderPaddingEnd(returnList);
-
- setFinished(true);
- return returnList;
- }
-
- /** {@inheritDoc} */
- public int getBaseLength(int lengthBase, FObj fobj) {
- return getParent().getBaseLength(lengthBase, getParent().getFObj());
- }
-
- /**
- * Returns the IPD of the content area
- * @return the IPD of the content area
- */
- public int getContentAreaIPD() {
- return contentAreaIPD;
- }
-
- private void setContentAreaIPD(int contentAreaIPD) {
- this.contentAreaIPD = contentAreaIPD;
- }
-
- /** {@inheritDoc} */
- public void reset() {
- childLMs.clear();
- super.reset();
- }
-
- }
|