001: /*
002: * Licensed to the Apache Software Foundation (ASF) under one or more
003: * contributor license agreements. See the NOTICE file distributed with
004: * this work for additional information regarding copyright ownership.
005: * The ASF licenses this file to You under the Apache License, Version 2.0
006: * (the "License"); you may not use this file except in compliance with
007: * the License. You may obtain a copy of the License at
008: *
009: * http://www.apache.org/licenses/LICENSE-2.0
010: *
011: * Unless required by applicable law or agreed to in writing, software
012: * distributed under the License is distributed on an "AS IS" BASIS,
013: * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
014: * See the License for the specific language governing permissions and
015: * limitations under the License.
016: */
017:
018: /* $Id: BalancingColumnBreakingAlgorithm.java 554094 2007-07-07 00:04:25Z adelmelle $ */
019:
020: package org.apache.fop.layoutmgr;
021:
022: import org.apache.commons.logging.Log;
023: import org.apache.commons.logging.LogFactory;
024: import org.apache.fop.traits.MinOptMax;
025:
026: /**
027: * This is a the breaking algorithm that is responsible for balancing columns in multi-column
028: * layout.
029: */
030: public class BalancingColumnBreakingAlgorithm extends
031: PageBreakingAlgorithm {
032:
033: private Log log = LogFactory
034: .getLog(BalancingColumnBreakingAlgorithm.class);
035:
036: private int columnCount;
037: private int fullLen;
038: private int idealPartLen;
039:
040: public BalancingColumnBreakingAlgorithm(LayoutManager topLevelLM,
041: PageProvider pageProvider,
042: PageBreakingLayoutListener layoutListener, int alignment,
043: int alignmentLast, MinOptMax footnoteSeparatorLength,
044: boolean partOverflowRecovery, int columnCount) {
045: super (topLevelLM, pageProvider, layoutListener, alignment,
046: alignmentLast, footnoteSeparatorLength,
047: partOverflowRecovery, false, false);
048: this .columnCount = columnCount;
049: this .considerTooShort = true; //This is important!
050: }
051:
052: /** @see org.apache.fop.layoutmgr.BreakingAlgorithm */
053: protected double computeDemerits(KnuthNode activeNode,
054: KnuthElement element, int fitnessClass, double r) {
055: double dem = super .computeDemerits(activeNode, element,
056: fitnessClass, r);
057: if (log.isTraceEnabled()) {
058: log.trace("original demerit=" + dem + " " + totalWidth
059: + " line=" + activeNode.line + "/" + columnCount
060: + " pos=" + activeNode.position + "/"
061: + (par.size() - 1));
062: }
063: int remParts = columnCount - activeNode.line;
064: int curPos = par.indexOf(element);
065: if (fullLen == 0) {
066: fullLen = ElementListUtils.calcContentLength(par,
067: activeNode.position, par.size() - 1);
068: this .idealPartLen = (fullLen / columnCount);
069: }
070: int partLen = ElementListUtils.calcContentLength(par,
071: activeNode.position, curPos - 1);
072: int restLen = ElementListUtils.calcContentLength(par,
073: curPos - 1, par.size() - 1);
074: int avgRestLen = 0;
075: if (remParts > 0) {
076: avgRestLen = restLen / remParts;
077: }
078: if (log.isTraceEnabled()) {
079: log.trace("remaining parts: " + remParts + " rest len: "
080: + restLen + " avg=" + avgRestLen);
081: }
082: double balance = (idealPartLen - partLen) / 1000f;
083: if (log.isTraceEnabled()) {
084: log.trace("balance=" + balance);
085: }
086: double absBalance = Math.abs(balance);
087: dem = absBalance;
088: //Step 1: This does the rough balancing
089: if (columnCount > 2) {
090: if (balance > 0) {
091: //shorter parts are less desired than longer ones
092: dem = dem * 1.2f;
093: }
094: } else {
095: if (balance < 0) {
096: //shorter parts are less desired than longer ones
097: dem = dem * 1.2f;
098: }
099: }
100: //Step 2: This helps keep the trailing parts shorter than the previous ones
101: dem += (avgRestLen) / 1000f;
102:
103: if (activeNode.line >= columnCount) {
104: //We don't want more columns than available
105: dem = Double.MAX_VALUE;
106: }
107: if (log.isTraceEnabled()) {
108: log.trace("effective dem=" + dem + " " + totalWidth);
109: }
110: return dem;
111: }
112: }
|