/*
 * 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: LineLayoutPossibilities.java 1681435 2015-05-24 11:14:22Z adelmelle $ */

package org.apache.fop.layoutmgr.inline;

import java.util.List;

import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;

Line layout possibilities.
/** * Line layout possibilities. */
public class LineLayoutPossibilities {
logger instance
/** logger instance */
private static final Log LOG = LogFactory.getLog(LineLayoutPossibilities.class); private final class Possibility { private int lineCount; private double demerits; private List<LineLayoutManager.LineBreakPosition> breakPositions; private Possibility(int lc, double dem) { lineCount = lc; demerits = dem; breakPositions = new java.util.ArrayList<LineLayoutManager.LineBreakPosition>(lc); } private int getLineCount() { return lineCount; } private double getDemerits() { return demerits; } private void addBreakPosition(LineLayoutManager.LineBreakPosition pos) { // Positions are always added with index 0 because // they are created backward, from the last one to // the first one breakPositions.add(0, pos); } private LineLayoutManager.LineBreakPosition getBreakPosition(int i) { return breakPositions.get(i); } } private List possibilitiesList; private List savedPossibilities; private int minimumIndex; private int optimumIndex; private int maximumIndex; private int chosenIndex; private int savedOptLineCount;
default constructor
/** default constructor */
public LineLayoutPossibilities() { possibilitiesList = new java.util.ArrayList(); savedPossibilities = new java.util.ArrayList(); optimumIndex = -1; }
Add possibility.
Params:
  • ln – line number
  • dem – demerits
/** * Add possibility. * @param ln line number * @param dem demerits */
public void addPossibility(int ln, double dem) { possibilitiesList.add(new Possibility(ln, dem)); if (possibilitiesList.size() == 1) { // first Possibility added minimumIndex = 0; optimumIndex = 0; maximumIndex = 0; chosenIndex = 0; } else { if (dem < ((Possibility)possibilitiesList.get(optimumIndex)).getDemerits()) { optimumIndex = possibilitiesList.size() - 1; chosenIndex = optimumIndex; } if (ln < ((Possibility)possibilitiesList.get(minimumIndex)).getLineCount()) { minimumIndex = possibilitiesList.size() - 1; } if (ln > ((Possibility)possibilitiesList.get(maximumIndex)).getLineCount()) { maximumIndex = possibilitiesList.size() - 1; } } }
Save in a different array the computed Possibilities, so possibilitiesList is ready to store different Possibilities.
Params:
  • bSaveOptLineCount – true if should save optimum line count
/** * Save in a different array the computed Possibilities, * so possibilitiesList is ready to store different Possibilities. * @param bSaveOptLineCount true if should save optimum line count */
public void savePossibilities(boolean bSaveOptLineCount) { if (bSaveOptLineCount) { savedOptLineCount = getOptLineCount(); } else { savedOptLineCount = 0; } savedPossibilities = possibilitiesList; possibilitiesList = new java.util.ArrayList(); }
Replace the Possibilities stored in possibilitiesList with the ones stored in savedPossibilities and having the same line number.
/** * Replace the Possibilities stored in possibilitiesList with * the ones stored in savedPossibilities and having the same line number. */
public void restorePossibilities() { int index = 0; while (savedPossibilities.size() > 0) { Possibility restoredPossibility = (Possibility) savedPossibilities.remove(0); if (restoredPossibility.getLineCount() < getMinLineCount()) { // if the line number of restoredPossibility is less than the minimum one, // add restoredPossibility at the beginning of the list possibilitiesList.add(0, restoredPossibility); // update minimumIndex minimumIndex = 0; // shift the other indexes; optimumIndex++; maximumIndex++; chosenIndex++; } else if (restoredPossibility.getLineCount() > getMaxLineCount()) { // if the line number of restoredPossibility is greater than the maximum one, // add restoredPossibility at the end of the list possibilitiesList.add(possibilitiesList.size(), restoredPossibility); // update maximumIndex maximumIndex = possibilitiesList.size() - 1; index = maximumIndex; } else { // find the index of the Possibility that will be replaced while (index < maximumIndex && getLineCount(index) < restoredPossibility.getLineCount()) { index++; } if (getLineCount(index) == restoredPossibility.getLineCount()) { possibilitiesList.set(index, restoredPossibility); } else { // this should not happen LOG.error("LineLayoutPossibilities restorePossibilities()," + " min= " + getMinLineCount() + " max= " + getMaxLineCount() + " restored= " + restoredPossibility.getLineCount()); return; } } // update optimumIndex and chosenIndex if (savedOptLineCount == 0 && getDemerits(optimumIndex) > restoredPossibility.getDemerits() || savedOptLineCount != 0 && restoredPossibility.getLineCount() == savedOptLineCount) { optimumIndex = index; chosenIndex = optimumIndex; } } //log.debug(">> minLineCount = " + getMinLineCount() // + " optLineCount = " + getOptLineCount() + " maxLineCount() = " + getMaxLineCount()); }
Params:
  • pos – a position
  • i – an index into posibilities list
/** * @param pos a position * @param i an index into posibilities list */
public void addBreakPosition(LineLayoutManager.LineBreakPosition pos, int i) { ((Possibility)possibilitiesList.get(i)).addBreakPosition(pos); }
Returns:true if can use more lines
/** @return true if can use more lines */
public boolean canUseMoreLines() { return (getOptLineCount() < getMaxLineCount()); }
Returns:true if can use fewer lines
/** @return true if can use fewer lines */
public boolean canUseLessLines() { return (getMinLineCount() < getOptLineCount()); }
Returns:the line count of the minimum index
/** @return the line count of the minimum index */
public int getMinLineCount() { return getLineCount(minimumIndex); }
Returns:the line count of the optimum index
/** @return the line count of the optimum index */
public int getOptLineCount() { return getLineCount(optimumIndex); }
Returns:the line count of the maximum index
/** @return the line count of the maximum index */
public int getMaxLineCount() { return getLineCount(maximumIndex); }
Returns:the line count of the chosen index
/** @return the line count of the chosen index */
public int getChosenLineCount() { return getLineCount(chosenIndex); }
Params:
  • i – the posibilities list index
Returns:the line count
/** * @param i the posibilities list index * @return the line count */
public int getLineCount(int i) { return ((Possibility)possibilitiesList.get(i)).getLineCount(); }
Returns:the demerits of the chosen index
/** @return the demerits of the chosen index */
public double getChosenDemerits() { return getDemerits(chosenIndex); }
Params:
  • i – the posibilities list index
Returns:the demerits
/** * @param i the posibilities list index * @return the demerits */
public double getDemerits(int i) { return ((Possibility)possibilitiesList.get(i)).getDemerits(); }
Returns:the possibilities count
/** @return the possibilities count */
public int getPossibilitiesNumber() { return possibilitiesList.size(); }
Params:
  • i – the break position index
Returns:the chosen position
/** * @param i the break position index * @return the chosen position */
public LineLayoutManager.LineBreakPosition getChosenPosition(int i) { return ((Possibility)possibilitiesList.get(chosenIndex)).getBreakPosition(i); }
Params:
  • adj – the adjustment
Returns:the adjustment or zero
/** * @param adj the adjustment * @return the adjustment or zero */
public int applyLineCountAdjustment(int adj) { if (adj >= (getMinLineCount() - getChosenLineCount()) && adj <= (getMaxLineCount() - getChosenLineCount()) && getLineCount(chosenIndex + adj) == getChosenLineCount() + adj) { chosenIndex += adj; LOG.debug("chosenLineCount= " + (getChosenLineCount() - adj) + " adjustment= " + adj + " => chosenLineCount= " + getLineCount(chosenIndex)); return adj; } else { // this should not happen! LOG.warn("Cannot apply the desired line count adjustment."); return 0; } }
print all
/** print all */
public void printAll() { System.out.println("++++++++++"); System.out.println(" " + possibilitiesList.size() + " possibility':"); for (int i = 0; i < possibilitiesList.size(); i++) { System.out.println(" " + ((Possibility)possibilitiesList.get(i)).getLineCount() + (i == optimumIndex ? " *" : "") + (i == minimumIndex ? " -" : "") + (i == maximumIndex ? " +" : "")); } System.out.println("++++++++++"); } }