View | Details | Raw Unified | Return to bug 46905
Collapse All | Expand All

(-)src/java/org/apache/fop/layoutmgr/StaticContentLayoutManager.java (-6 / +6 lines)
Lines 415-432 Link Here
415
    }
415
    }
416
416
417
    /** {@inheritDoc} */
417
    /** {@inheritDoc} */
418
    public int getKeepTogetherStrength() {
418
    public Keep getKeepTogether() {
419
        return KEEP_AUTO;
419
        return Keep.KEEP_AUTO;
420
    }
420
    }
421
421
422
    /** {@inheritDoc} */
422
    /** {@inheritDoc} */
423
    public int getKeepWithNextStrength() {
423
    public Keep getKeepWithNext() {
424
        return KEEP_AUTO;
424
        return Keep.KEEP_AUTO;
425
    }
425
    }
426
426
427
    /** {@inheritDoc} */
427
    /** {@inheritDoc} */
428
    public int getKeepWithPreviousStrength() {
428
    public Keep getKeepWithPrevious() {
429
        return KEEP_AUTO;
429
        return Keep.KEEP_AUTO;
430
    }
430
    }
431
431
432
}
432
}
(-)src/java/org/apache/fop/layoutmgr/KeepUtil.java (-109 lines)
Lines 1-109 Link Here
1
/*
2
 * Licensed to the Apache Software Foundation (ASF) under one or more
3
 * contributor license agreements.  See the NOTICE file distributed with
4
 * this work for additional information regarding copyright ownership.
5
 * The ASF licenses this file to You under the Apache License, Version 2.0
6
 * (the "License"); you may not use this file except in compliance with
7
 * the License.  You may obtain a copy of the License at
8
 *
9
 *      http://www.apache.org/licenses/LICENSE-2.0
10
 *
11
 * Unless required by applicable law or agreed to in writing, software
12
 * distributed under the License is distributed on an "AS IS" BASIS,
13
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14
 * See the License for the specific language governing permissions and
15
 * limitations under the License.
16
 */
17
18
/* $Id$ */
19
20
package org.apache.fop.layoutmgr;
21
22
import org.apache.fop.fo.Constants;
23
import org.apache.fop.fo.properties.KeepProperty;
24
import org.apache.fop.fo.properties.Property;
25
26
/**
27
 * Utility class for working with keeps.
28
 */
29
public class KeepUtil {
30
31
    /**
32
     * Converts a keep property into an integer value.
33
     * <p>
34
     * Note: The conversion restricts the effectively available integer range by two values.
35
     * Integer.MIN_VALUE is used to represent the value "auto" and
36
     * Integer.MAX_VALUE is used to represebt the value "always".
37
     * @param keep the keep property
38
     * @return the keep value as an integer
39
     */
40
    public static int getKeepStrength(Property keep) {
41
        if (keep.isAuto()) {
42
            return BlockLevelLayoutManager.KEEP_AUTO;
43
        } else if (keep.getEnum() == Constants.EN_ALWAYS) {
44
            return BlockLevelLayoutManager.KEEP_ALWAYS;
45
        } else {
46
            return keep.getNumber().intValue();
47
        }
48
    }
49
50
    /**
51
     * Returns the combined block-level keep strength from a keep property.
52
     * <p>
53
     * Note: This is a temporary method to be used until it is possible to differentiate between
54
     * page and column keeps!
55
     * @param keep the keep property
56
     * @return the combined keep strength
57
     */
58
    public static int getCombinedBlockLevelKeepStrength(KeepProperty keep) {
59
        return Math.max(
60
                getKeepStrength(keep.getWithinPage()),
61
                getKeepStrength(keep.getWithinColumn()));
62
    }
63
64
    /**
65
     * Indicates whether a keep strength indicates a keep constraint.
66
     * @param strength the keep strength
67
     * @return true if the keep is not "auto"
68
     */
69
    public static boolean hasKeep(int strength) {
70
        return strength > BlockLevelLayoutManager.KEEP_AUTO;
71
    }
72
73
    /**
74
     * Returns the penalty value to be used for a certain keep strength.
75
     * <ul>
76
     *   <li>"auto": returns 0</li>
77
     *   <li>"always": returns KnuthElement.INFINITE</li>
78
     *   <li>otherwise: returns KnuthElement.INFINITE - 1</li>
79
     * </ul>
80
     * @param keepStrength the keep strength
81
     * @return the penalty value
82
     */
83
    public static int getPenaltyForKeep(int keepStrength) {
84
        if (keepStrength == BlockLevelLayoutManager.KEEP_AUTO) {
85
            return 0;
86
        }
87
        int penalty = KnuthElement.INFINITE;
88
        if (keepStrength < BlockLevelLayoutManager.KEEP_ALWAYS) {
89
            penalty--;
90
        }
91
        return penalty;
92
    }
93
94
    /**
95
     * Returns a string representation of a keep strength value.
96
     * @param keepStrength the keep strength
97
     * @return the string representation
98
     */
99
    public static String keepStrengthToString(int keepStrength) {
100
        if (keepStrength == BlockLevelLayoutManager.KEEP_AUTO) {
101
            return "auto";
102
        } else if (keepStrength == BlockLevelLayoutManager.KEEP_ALWAYS) {
103
            return "always";
104
        } else {
105
            return Integer.toString(keepStrength);
106
        }
107
    }
108
109
}
(-)src/java/org/apache/fop/layoutmgr/KnuthPenalty.java (-48 / +42 lines)
Lines 45-51 Link Here
45
    public static final int FLAGGED_PENALTY = 50;
45
    public static final int FLAGGED_PENALTY = 50;
46
46
47
    private int penalty;
47
    private int penalty;
48
    private boolean bFlagged;
48
    private boolean isFlagged;
49
    private int breakClass = -1;
49
    private int breakClass = -1;
50
50
51
    /**
51
    /**
Lines 55-66 Link Here
55
     * @param p the penalty value of this penalty
55
     * @param p the penalty value of this penalty
56
     * @param f is this penalty flagged?
56
     * @param f is this penalty flagged?
57
     * @param pos the Position stored in this penalty
57
     * @param pos the Position stored in this penalty
58
     * @param bAux is this penalty auxiliary?
58
     * @param isAuxiliary is this penalty auxiliary?
59
     */
59
     */
60
    public KnuthPenalty(int w, int p, boolean f, Position pos, boolean bAux) {
60
    public KnuthPenalty(int w, int p, boolean f, Position pos, boolean isAuxiliary) {
61
        super(w, pos, bAux);
61
        super(w, pos, isAuxiliary);
62
        penalty = p;
62
        penalty = p;
63
        bFlagged = f;
63
        isFlagged = f;
64
    }
64
    }
65
65
66
    /**
66
    /**
Lines 69-88 Link Here
69
     * @param w the width of this penalty
69
     * @param w the width of this penalty
70
     * @param p the penalty value of this penalty
70
     * @param p the penalty value of this penalty
71
     * @param f is this penalty flagged?
71
     * @param f is this penalty flagged?
72
     * @param iBreakClass the break class of this penalty (one of
72
     * @param breakClass the break class of this penalty (one of
73
     * {@link Constants#EN_AUTO}, {@link Constants#EN_COLUMN}, {@link Constants#EN_PAGE},
73
     * {@link Constants#EN_AUTO}, {@link Constants#EN_COLUMN}, {@link Constants#EN_PAGE},
74
     * {@link Constants#EN_EVEN_PAGE}, {@link Constants#EN_ODD_PAGE})
74
     * {@link Constants#EN_EVEN_PAGE}, {@link Constants#EN_ODD_PAGE})
75
     * @param pos the Position stored in this penalty
75
     * @param pos the Position stored in this penalty
76
     * @param bAux is this penalty auxiliary?
76
     * @param isAuxiliary is this penalty auxiliary?
77
     */
77
     */
78
    public KnuthPenalty(int w, int p, boolean f,
78
    public KnuthPenalty(int w, int p, boolean f,
79
            int iBreakClass, Position pos, boolean bAux) {
79
            int breakClass, Position pos, boolean isAuxiliary) {
80
        super(w, pos, bAux);
80
        this(w, p, f, pos, isAuxiliary);
81
        penalty = p;
81
        this.breakClass = breakClass;
82
        bFlagged = f;
83
        breakClass = iBreakClass;
84
    }
82
    }
85
83
84
    private static String getBreakClassName(int breakClass) {
85
        return AbstractBreaker.getBreakClassName(breakClass);
86
    }
87
88
    /**
89
     * Get the penalty's value as a {@code java.lang.String}.
90
     * (Mainly used in {@code toString()} methods, to improve readability
91
     * of the trace logs.)
92
     *
93
     * @param penaltyValue  the penalty value
94
     * @return  the penalty value as a {@code java.lang.String}
95
     */
96
    protected static String valueOf(int penaltyValue) {
97
        String result = (penaltyValue < 0) ? "-" : "";
98
        int tmpValue = Math.abs(penaltyValue);
99
        result += (tmpValue == KnuthElement.INFINITE)
100
                ? "INFINITE"
101
                : String.valueOf(tmpValue);
102
        return result;
103
    }
104
86
    /** {@inheritDoc} */
105
    /** {@inheritDoc} */
87
    public boolean isPenalty() {
106
    public boolean isPenalty() {
88
        return true;
107
        return true;
Lines 105-111 Link Here
105
124
106
    /** @return true is this penalty is a flagged one. */
125
    /** @return true is this penalty is a flagged one. */
107
    public boolean isFlagged() {
126
    public boolean isFlagged() {
108
        return bFlagged;
127
        return isFlagged;
109
    }
128
    }
110
129
111
    /** {@inheritDoc} */
130
    /** {@inheritDoc} */
Lines 121-134 Link Here
121
        return breakClass;
140
        return breakClass;
122
    }
141
    }
123
142
124
    /**
125
     * Sets the break class for this penalty.
126
     * @param cl the break class (EN_AUTO, EN_COLUMN, EN_PAGE, EN_EVEN_PAGE, EN_ODD_PAGE)
127
     */
128
    public void setBreakClass(int cl) {
129
        this.breakClass = cl;
130
    }
131
132
    /** {@inheritDoc} */
143
    /** {@inheritDoc} */
133
    public String toString() {
144
    public String toString() {
134
        StringBuffer sb = new StringBuffer(64);
145
        StringBuffer sb = new StringBuffer(64);
Lines 137-175 Link Here
137
        }
148
        }
138
        sb.append("penalty");
149
        sb.append("penalty");
139
        sb.append(" p=");
150
        sb.append(" p=");
140
        if (getP() < 0) {
151
        sb.append(valueOf(this.penalty));
141
            sb.append("-");
152
        if (this.isFlagged) {
142
        }
143
        if (Math.abs(getP()) == INFINITE) {
144
            sb.append("INFINITE");
145
        } else {
146
            sb.append(getP());
147
        }
148
        if (isFlagged()) {
149
            sb.append(" [flagged]");
153
            sb.append(" [flagged]");
150
        }
154
        }
151
        sb.append(" w=");
155
        sb.append(" w=");
152
        sb.append(getW());
156
        sb.append(getW());
153
        if (isForcedBreak()) {
157
        if (isForcedBreak()) {
154
            sb.append(" (forced break");
158
            sb.append(" (forced break, ")
155
            switch (getBreakClass()) {
159
                    .append(getBreakClassName(this.breakClass))
156
            case Constants.EN_PAGE:
160
                    .append(")");
157
                sb.append(", page");
161
        } else if (this.penalty >= 0 && this.breakClass != -1) {
158
                break;
162
            //penalty corresponding to a keep constraint
159
            case Constants.EN_COLUMN:
163
            sb.append(" (keep constraint, ")
160
                sb.append(", column");
164
                    .append(getBreakClassName(this.breakClass))
161
                break;
165
                    .append(")");
162
            case Constants.EN_EVEN_PAGE:
163
                sb.append(", even page");
164
                break;
165
            case Constants.EN_ODD_PAGE:
166
                sb.append(", odd page");
167
                break;
168
            default:
169
            }
170
            sb.append(")");
171
        }
166
        }
172
        return sb.toString();
167
        return sb.toString();
173
    }
168
    }
174
175
}
169
}
(-)src/java/org/apache/fop/layoutmgr/inline/LineLayoutManager.java (-178 / +38 lines)
Lines 36-41 Link Here
36
import org.apache.fop.fo.Constants;
36
import org.apache.fop.fo.Constants;
37
import org.apache.fop.fo.flow.Block;
37
import org.apache.fop.fo.flow.Block;
38
import org.apache.fop.fo.properties.CommonHyphenation;
38
import org.apache.fop.fo.properties.CommonHyphenation;
39
import org.apache.fop.fo.properties.KeepProperty;
39
import org.apache.fop.fonts.Font;
40
import org.apache.fop.fonts.Font;
40
import org.apache.fop.fonts.FontInfo;
41
import org.apache.fop.fonts.FontInfo;
41
import org.apache.fop.fonts.FontTriplet;
42
import org.apache.fop.fonts.FontTriplet;
Lines 46-52 Link Here
46
import org.apache.fop.layoutmgr.BreakingAlgorithm;
47
import org.apache.fop.layoutmgr.BreakingAlgorithm;
47
import org.apache.fop.layoutmgr.ElementListObserver;
48
import org.apache.fop.layoutmgr.ElementListObserver;
48
import org.apache.fop.layoutmgr.InlineKnuthSequence;
49
import org.apache.fop.layoutmgr.InlineKnuthSequence;
49
import org.apache.fop.layoutmgr.KeepUtil;
50
import org.apache.fop.layoutmgr.Keep;
50
import org.apache.fop.layoutmgr.KnuthBlockBox;
51
import org.apache.fop.layoutmgr.KnuthBlockBox;
51
import org.apache.fop.layoutmgr.KnuthBox;
52
import org.apache.fop.layoutmgr.KnuthBox;
52
import org.apache.fop.layoutmgr.KnuthElement;
53
import org.apache.fop.layoutmgr.KnuthElement;
Lines 169-175 Link Here
169
    private AlignmentContext alignmentContext = null;
170
    private AlignmentContext alignmentContext = null;
170
171
171
    private List knuthParagraphs = null;
172
    private List knuthParagraphs = null;
172
    private int iReturnedLBP = 0;
173
173
174
    //     parameters of Knuth's algorithm:
174
    //     parameters of Knuth's algorithm:
175
    // penalty value for flagged penalties
175
    // penalty value for flagged penalties
Lines 605-638 Link Here
605
605
606
        //PHASE 2: Create line breaks
606
        //PHASE 2: Create line breaks
607
        return createLineBreaks(context.getBPAlignment(), context);
607
        return createLineBreaks(context.getBPAlignment(), context);
608
        /*
609
        LineBreakPosition lbp = null;
610
        if (breakpoints == null) {
611
            // find the optimal line breaking points for each paragraph
612
            breakpoints = new ArrayList();
613
            ListIterator paragraphsIterator
614
                = knuthParagraphs.listIterator(knuthParagraphs.size());
615
            Paragraph currPar = null;
616
            while (paragraphsIterator.hasPrevious()) {
617
                currPar = (Paragraph) paragraphsIterator.previous();
618
                findBreakingPoints(currPar, context.getStackLimit().opt);
619
            }
620
        }*/
621
622
        //PHASE 3: Return lines
623
624
        /*
625
        // get a break point from the list
626
        lbp = (LineBreakPosition) breakpoints.get(iReturnedLBP ++);
627
        if (iReturnedLBP == breakpoints.size()) {
628
            setFinished(true);
629
        }
630
631
        BreakPoss curLineBP = new BreakPoss(lbp);
632
        curLineBP.setFlag(BreakPoss.ISLAST, isFinished());
633
        curLineBP.setStackingSize(new MinOptMax(lbp.lineHeight));
634
        return curLineBP;
635
        */
636
    }
608
    }
637
609
638
    /**
610
    /**
Lines 767-900 Link Here
767
    }
739
    }
768
740
769
    /**
741
    /**
770
     * Find a set of breaking points.
771
     * This method is called only once by getNextBreakPoss, and it
772
     * subsequently calls the other findBreakingPoints() method with
773
     * different parameters, until a set of breaking points is found.
774
     *
775
     * @param par       the list of elements that must be parted
776
     *                  into lines
777
     * @param lineWidth the desired length ot the lines
778
     */
779
    /*
780
    private void findBreakingPoints(Paragraph par, int lineWidth) {
781
        // maximum adjustment ratio permitted
782
        float maxAdjustment = 1;
783
784
        // first try
785
        if (!findBreakingPoints(par, lineWidth, maxAdjustment, false)) {
786
            // the first try failed, now try something different
787
            log.debug("No set of breaking points found with maxAdjustment = " + maxAdjustment);
788
            if (hyphenationProperties.hyphenate == Constants.EN_TRUE) {
789
                // consider every hyphenation point as a legal break
790
                findHyphenationPoints(par);
791
            } else {
792
                // try with a higher threshold
793
                maxAdjustment = 5;
794
            }
795
796
            if (!findBreakingPoints(par, lineWidth, maxAdjustment, false)) {
797
                // the second try failed too, try with a huge threshold;
798
                // if this fails too, use a different algorithm
799
                log.debug("No set of breaking points found with maxAdjustment = " + maxAdjustment
800
                          + (hyphenationProperties.hyphenate == Constants.EN_TRUE ? " and hyphenation" : ""));
801
                maxAdjustment = 20;
802
                if (!findBreakingPoints(par, lineWidth, maxAdjustment, true)) {
803
                    log.debug("No set of breaking points found, using first-fit algorithm");
804
                }
805
            }
806
        }
807
    }
808
809
    private boolean findBreakingPoints(Paragraph par, int lineWidth,
810
            double threshold, boolean force) {
811
        KnuthParagraph knuthPara = new KnuthParagraph(par);
812
        int lines = knuthPara.findBreakPoints(lineWidth, threshold, force);
813
        if (lines == 0) {
814
            return false;
815
        }
816
817
        for (int i = lines-1; i >= 0; i--) {
818
            int line = i+1;
819
            if (log.isTraceEnabled()) {
820
                log.trace("Making line from " + knuthPara.getStart(i) + " to " +
821
                           knuthPara.getEnd(i));
822
            }
823
            // compute indent and adjustment ratio, according to
824
            // the value of text-align and text-align-last
825
826
            int difference = knuthPara.getDifference(i);
827
            if (line == lines) {
828
                difference += par.lineFillerWidth;
829
            }
830
            int textAlign = (line < lines)
831
                ? textAlignment : textAlignmentLast;
832
            int indent = (textAlign == EN_CENTER)
833
                ? difference / 2
834
                : (textAlign == EN_END) ? difference : 0;
835
            indent += (line == 1 && knuthParagraphs.indexOf(par) == 0)
836
                ? textIndent.getValue(this) : 0;
837
            double ratio = (textAlign == EN_JUSTIFY)
838
                ? knuthPara.getAdjustRatio(i) : 0;
839
840
            int start = knuthPara.getStart(i);
841
            int end = knuthPara.getEnd(i);
842
            makeLineBreakPosition(par, start, end, 0, ratio, indent);
843
        }
844
        return true;
845
    }
846
847
    private void makeLineBreakPosition(Paragraph par,
848
                                       int firstElementIndex, int lastElementIndex,
849
                                       int insertIndex, double ratio, int indent) {
850
        // line height calculation
851
852
        int halfLeading = (lineHeight - lead - follow) / 2;
853
        // height above the main baseline
854
        int lineLead = lead + halfLeading;
855
        // maximum size of top and bottom alignment
856
        int lineFollow = follow + halfLeading;
857
858
        ListIterator inlineIterator
859
            = par.listIterator(firstElementIndex);
860
        for (int j = firstElementIndex;
861
             j <= lastElementIndex;
862
             j++) {
863
            KnuthElement element = (KnuthElement) inlineIterator.next();
864
            if (element.isBox()) {
865
                KnuthInlineBox box = (KnuthInlineBox)element;
866
                if (box.getLead() > lineLead) {
867
                    lineLead = box.getLead();
868
                }
869
                if (box.getTotal() > lineFollow) {
870
                    lineFollow = box.getTotal();
871
                }
872
                if (box.getMiddle() > lineLead + middleShift) {
873
                    lineLead += box.getMiddle()
874
                                - lineLead - middleShift;
875
                }
876
                if (box.getMiddle() > middlefollow - middleShift) {
877
                    middlefollow += box.getMiddle()
878
                                    - middlefollow + middleShift;
879
                }
880
            }
881
        }
882
883
        if (lineFollow - lineLead > middlefollow) {
884
                    middlefollow = lineFollow - lineLead;
885
        }
886
887
        breakpoints.add(insertIndex,
888
                        new LineBreakPosition(this,
889
                                              knuthParagraphs.indexOf(par),
890
                                              lastElementIndex ,
891
                                              ratio, 0, indent,
892
                                              lineLead + middlefollow,
893
                                              lineLead));
894
    }*/
895
896
897
    /**
898
     * Phase 2 of Knuth algorithm: find optimal break points.
742
     * Phase 2 of Knuth algorithm: find optimal break points.
899
     * @param alignment alignment in BP direction of the paragraph
743
     * @param alignment alignment in BP direction of the paragraph
900
     * @param context the layout context
744
     * @param context the layout context
Lines 1054-1065 Link Here
1054
        for (int p = 0; p < knuthParagraphs.size(); p++) {
898
        for (int p = 0; p < knuthParagraphs.size(); p++) {
1055
            // penalty between paragraphs
899
            // penalty between paragraphs
1056
            if (p > 0) {
900
            if (p > 0) {
1057
                int strength = getKeepTogetherStrength();
901
                Keep keep = getKeepTogether();
1058
                int penalty = KeepUtil.getPenaltyForKeep(strength);
902
                returnList.add(new BreakElement(
1059
                if (penalty < KnuthElement.INFINITE) {
903
                            new Position(this),
1060
                    returnList.add(new BreakElement(
904
                            keep.getPenalty(),
1061
                            new Position(this), penalty, context));
905
                            keep.getContext(),
1062
                }
906
                            context));
1063
            }
907
            }
1064
908
1065
            LineLayoutPossibilities llPoss;
909
            LineLayoutPossibilities llPoss;
Lines 1098-1109 Link Here
1098
                            && i >= fobj.getOrphans()
942
                            && i >= fobj.getOrphans()
1099
                            && i <= llPoss.getChosenLineCount() - fobj.getWidows()) {
943
                            && i <= llPoss.getChosenLineCount() - fobj.getWidows()) {
1100
                        // penalty allowing a page break between lines
944
                        // penalty allowing a page break between lines
1101
                        int strength = getKeepTogetherStrength();
945
                        Keep keep = getKeepTogether();
1102
                        int penalty = KeepUtil.getPenaltyForKeep(strength);
946
                        returnList.add(new BreakElement(
1103
                        if (penalty < KnuthElement.INFINITE) {
947
                                    new Position(this),
1104
                            returnList.add(new BreakElement(
948
                                    keep.getPenalty(),
1105
                                    returnPosition, penalty, context));
949
                                    keep.getContext(),
1106
                        }
950
                                    context));
1107
                    }
951
                    }
1108
                    int endIndex
952
                    int endIndex
1109
                      = ((LineBreakPosition) llPoss.getChosenPosition(i)).getLeafPos();
953
                      = ((LineBreakPosition) llPoss.getChosenPosition(i)).getLeafPos();
Lines 1283-1310 Link Here
1283
    }
1127
    }
1284
1128
1285
    /** {@inheritDoc} */
1129
    /** {@inheritDoc} */
1286
    public int getKeepTogetherStrength() {
1130
    public KeepProperty getKeepTogetherProperty() {
1287
        return ((BlockLevelLayoutManager) getParent()).getKeepTogetherStrength();
1131
        return ((BlockLevelLayoutManager) getParent()).getKeepTogetherProperty();
1288
    }
1132
    }
1289
1133
1290
    /** {@inheritDoc} */
1134
    /** {@inheritDoc} */
1135
    public KeepProperty getKeepWithPreviousProperty() {
1136
        return ((BlockLevelLayoutManager) getParent()).getKeepWithPreviousProperty();
1137
    }
1138
1139
    /** {@inheritDoc} */
1140
    public KeepProperty getKeepWithNextProperty() {
1141
        return ((BlockLevelLayoutManager) getParent()).getKeepWithNextProperty();
1142
    }
1143
1144
    /** {@inheritDoc} */
1145
    public Keep getKeepTogether() {
1146
        return ((BlockLevelLayoutManager) getParent()).getKeepTogether();
1147
    }
1148
1149
    /** {@inheritDoc} */
1291
    public boolean mustKeepWithPrevious() {
1150
    public boolean mustKeepWithPrevious() {
1292
        return getKeepWithPreviousStrength() > KEEP_AUTO;
1151
        return !getKeepWithPrevious().isAuto();
1293
    }
1152
    }
1294
1153
1295
    /** {@inheritDoc} */
1154
    /** {@inheritDoc} */
1296
    public boolean mustKeepWithNext() {
1155
    public boolean mustKeepWithNext() {
1297
        return getKeepWithNextStrength() > KEEP_AUTO;
1156
        return !getKeepWithNext().isAuto();
1298
    }
1157
    }
1299
1158
1300
    /** {@inheritDoc} */
1159
    /** {@inheritDoc} */
1301
    public int getKeepWithNextStrength() {
1160
    public Keep getKeepWithNext() {
1302
        return KEEP_AUTO;
1161
        return Keep.KEEP_AUTO;
1303
    }
1162
    }
1304
1163
1305
    /** {@inheritDoc} */
1164
    /** {@inheritDoc} */
1306
    public int getKeepWithPreviousStrength() {
1165
    public Keep getKeepWithPrevious() {
1307
        return KEEP_AUTO;
1166
        return Keep.KEEP_AUTO;
1308
    }
1167
    }
1309
1168
1310
    /** {@inheritDoc} */
1169
    /** {@inheritDoc} */
Lines 1409-1414 Link Here
1409
                break;
1268
                break;
1410
            }
1269
            }
1411
            //TODO Something's not right here. See block_hyphenation_linefeed_preserve.xml
1270
            //TODO Something's not right here. See block_hyphenation_linefeed_preserve.xml
1271
            //for more info: see also https://issues.apache.org/bugzilla/show_bug.cgi?id=38264
1412
1272
1413
            // collect word fragments, ignoring auxiliary elements;
1273
            // collect word fragments, ignoring auxiliary elements;
1414
            // each word fragment was created by a different TextLM
1274
            // each word fragment was created by a different TextLM
(-)src/java/org/apache/fop/layoutmgr/BlockLevelLayoutManager.java (-8 / +22 lines)
Lines 19-24 Link Here
19
19
20
package org.apache.fop.layoutmgr;
20
package org.apache.fop.layoutmgr;
21
21
22
import org.apache.fop.fo.properties.KeepProperty;
23
22
/**
24
/**
23
 * The interface for LayoutManagers which generate block areas
25
 * The interface for LayoutManagers which generate block areas
24
 */
26
 */
Lines 35-45 Link Here
35
    /** Adjustment class: adjustment for line height */
37
    /** Adjustment class: adjustment for line height */
36
    int LINE_HEIGHT_ADJUSTMENT = 3;
38
    int LINE_HEIGHT_ADJUSTMENT = 3;
37
39
38
    /** The integer value for "auto" keep strength */
39
    int KEEP_AUTO = Integer.MIN_VALUE;
40
    /** The integer value for "always" keep strength */
41
    int KEEP_ALWAYS = Integer.MAX_VALUE;
42
43
    int negotiateBPDAdjustment(int adj, KnuthElement lastElement);
40
    int negotiateBPDAdjustment(int adj, KnuthElement lastElement);
44
41
45
    void discardSpace(KnuthGlue spaceGlue);
42
    void discardSpace(KnuthGlue spaceGlue);
Lines 48-54 Link Here
48
     * Returns the keep-together strength for this element.
45
     * Returns the keep-together strength for this element.
49
     * @return the keep-together strength
46
     * @return the keep-together strength
50
     */
47
     */
51
    int getKeepTogetherStrength();
48
    Keep getKeepTogether();
52
49
53
    /**
50
    /**
54
     * @return true if this element must be kept together
51
     * @return true if this element must be kept together
Lines 59-65 Link Here
59
     * Returns the keep-with-previous strength for this element.
56
     * Returns the keep-with-previous strength for this element.
60
     * @return the keep-with-previous strength
57
     * @return the keep-with-previous strength
61
     */
58
     */
62
    int getKeepWithPreviousStrength();
59
    Keep getKeepWithPrevious();
63
60
64
    /**
61
    /**
65
     * @return true if this element must be kept with the previous element.
62
     * @return true if this element must be kept with the previous element.
Lines 70-80 Link Here
70
     * Returns the keep-with-next strength for this element.
67
     * Returns the keep-with-next strength for this element.
71
     * @return the keep-with-next strength
68
     * @return the keep-with-next strength
72
     */
69
     */
73
    int getKeepWithNextStrength();
70
    Keep getKeepWithNext();
74
71
75
    /**
72
    /**
76
     * @return true if this element must be kept with the next element.
73
     * @return true if this element must be kept with the next element.
77
     */
74
     */
78
    boolean mustKeepWithNext();
75
    boolean mustKeepWithNext();
79
76
77
    /**
78
     * Returns the keep-together property specified on the FObj.
79
     * @return the keep-together property
80
     */
81
    KeepProperty getKeepTogetherProperty();
82
83
    /**
84
     * Returns the keep-with-previous property specified on the FObj.
85
     * @return the keep-together property
86
     */
87
    KeepProperty getKeepWithPreviousProperty();
88
89
    /**
90
     * Returns the keep-with-next property specified on the FObj.
91
     * @return the keep-together property
92
     */
93
    KeepProperty getKeepWithNextProperty();
80
}
94
}
(-)src/java/org/apache/fop/layoutmgr/LayoutContext.java (-17 / +16 lines)
Lines 145-152 Link Here
145
    private int breakBefore;
145
    private int breakBefore;
146
    private int breakAfter;
146
    private int breakAfter;
147
147
148
    private int pendingKeepWithNext = BlockLevelLayoutManager.KEEP_AUTO;
148
    private Keep pendingKeepWithNext = Keep.KEEP_AUTO;
149
    private int pendingKeepWithPrevious = BlockLevelLayoutManager.KEEP_AUTO;
149
    private Keep pendingKeepWithPrevious = Keep.KEEP_AUTO;
150
150
151
    private int disableColumnBalancing;
151
    private int disableColumnBalancing;
152
152
Lines 237-243 Link Here
237
     * Returns the strength of a keep-with-next currently pending.
237
     * Returns the strength of a keep-with-next currently pending.
238
     * @return the keep-with-next strength
238
     * @return the keep-with-next strength
239
     */
239
     */
240
    public int getKeepWithNextPending() {
240
    public Keep getKeepWithNextPending() {
241
        return this.pendingKeepWithNext;
241
        return this.pendingKeepWithNext;
242
    }
242
    }
243
243
Lines 245-251 Link Here
245
     * Returns the strength of a keep-with-previous currently pending.
245
     * Returns the strength of a keep-with-previous currently pending.
246
     * @return the keep-with-previous strength
246
     * @return the keep-with-previous strength
247
     */
247
     */
248
    public int getKeepWithPreviousPending() {
248
    public Keep getKeepWithPreviousPending() {
249
        return this.pendingKeepWithPrevious;
249
        return this.pendingKeepWithPrevious;
250
    }
250
    }
251
251
Lines 253-266 Link Here
253
     * Clears any pending keep-with-next strength.
253
     * Clears any pending keep-with-next strength.
254
     */
254
     */
255
    public void clearKeepWithNextPending() {
255
    public void clearKeepWithNextPending() {
256
        this.pendingKeepWithNext = BlockLevelLayoutManager.KEEP_AUTO;
256
        this.pendingKeepWithNext = Keep.KEEP_AUTO;
257
    }
257
    }
258
258
259
    /**
259
    /**
260
     * Clears any pending keep-with-previous strength.
260
     * Clears any pending keep-with-previous strength.
261
     */
261
     */
262
    public void clearKeepWithPreviousPending() {
262
    public void clearKeepWithPreviousPending() {
263
        this.pendingKeepWithPrevious = BlockLevelLayoutManager.KEEP_AUTO;
263
        this.pendingKeepWithPrevious = Keep.KEEP_AUTO;
264
    }
264
    }
265
265
266
    /**
266
    /**
Lines 273-290 Link Here
273
273
274
    /**
274
    /**
275
     * Updates the currently pending keep-with-next strength.
275
     * Updates the currently pending keep-with-next strength.
276
     * @param strength the new strength to consider
276
     * @param keep the new strength to consider
277
     */
277
     */
278
    public void updateKeepWithNextPending(int strength) {
278
    public void updateKeepWithNextPending(Keep keep) {
279
        this.pendingKeepWithNext = Math.max(this.pendingKeepWithNext, strength);
279
        this.pendingKeepWithNext = this.pendingKeepWithNext.compare(keep);
280
    }
280
    }
281
281
282
    /**
282
    /**
283
     * Updates the currently pending keep-with-previous strength.
283
     * Updates the currently pending keep-with-previous strength.
284
     * @param strength the new strength to consider
284
     * @param keep the new strength to consider
285
     */
285
     */
286
    public void updateKeepWithPreviousPending(int strength) {
286
    public void updateKeepWithPreviousPending(Keep keep) {
287
        this.pendingKeepWithPrevious = Math.max(this.pendingKeepWithPrevious, strength);
287
        this.pendingKeepWithPrevious = this.pendingKeepWithPrevious.compare(keep);
288
    }
288
    }
289
289
290
    /**
290
    /**
Lines 292-298 Link Here
292
     * @return true if a keep-with-next constraint is pending
292
     * @return true if a keep-with-next constraint is pending
293
     */
293
     */
294
    public boolean isKeepWithNextPending() {
294
    public boolean isKeepWithNextPending() {
295
        return getKeepWithNextPending() != BlockLevelLayoutManager.KEEP_AUTO;
295
        return !getKeepWithNextPending().isAuto();
296
    }
296
    }
297
297
298
    /**
298
    /**
Lines 300-306 Link Here
300
     * @return true if a keep-with-previous constraint is pending
300
     * @return true if a keep-with-previous constraint is pending
301
     */
301
     */
302
    public boolean isKeepWithPreviousPending() {
302
    public boolean isKeepWithPreviousPending() {
303
        return getKeepWithPreviousPending() != BlockLevelLayoutManager.KEEP_AUTO;
303
        return !getKeepWithPreviousPending().isAuto();
304
    }
304
    }
305
305
306
    public void setLeadingSpace(SpaceSpecifier space) {
306
    public void setLeadingSpace(SpaceSpecifier space) {
Lines 677-685 Link Here
677
        + "\nStarts New Area: \t" + startsNewArea()
677
        + "\nStarts New Area: \t" + startsNewArea()
678
        + "\nIs Last Area: \t" + isLastArea()
678
        + "\nIs Last Area: \t" + isLastArea()
679
        + "\nTry Hyphenate: \t" + tryHyphenate()
679
        + "\nTry Hyphenate: \t" + tryHyphenate()
680
        + "\nKeeps: \t[keep-with-next=" + KeepUtil.keepStrengthToString(getKeepWithNextPending())
680
        + "\nKeeps: \t[keep-with-next=" + getKeepWithNextPending()
681
                + "][keep-with-previous="
681
                + "][keep-with-previous=" + getKeepWithPreviousPending() + "] pending"
682
                + KeepUtil.keepStrengthToString(getKeepWithPreviousPending()) + "] pending"
683
        + "\nBreaks: \tforced [" + (breakBefore != Constants.EN_AUTO ? "break-before" : "") + "]["
682
        + "\nBreaks: \tforced [" + (breakBefore != Constants.EN_AUTO ? "break-before" : "") + "]["
684
        + (breakAfter != Constants.EN_AUTO ? "break-after" : "") + "]";
683
        + (breakAfter != Constants.EN_AUTO ? "break-after" : "") + "]";
685
    }
684
    }
(-)src/java/org/apache/fop/layoutmgr/Keep.java (+152 lines)
Line 0 Link Here
1
/*
2
 * Licensed to the Apache Software Foundation (ASF) under one or more contributor license
3
 * agreements. See the NOTICE file distributed with this work for additional information
4
 * regarding copyright ownership. The ASF licenses this file to You under the Apache
5
 * License, Version 2.0 (the "License"); you may not use this file except in compliance
6
 * with the License. You may obtain a copy of the License at
7
 *
8
 * http://www.apache.org/licenses/LICENSE-2.0
9
 *
10
 * Unless required by applicable law or agreed to in writing, software distributed under
11
 * the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
12
 * KIND, either express or implied. See the License for the specific language governing
13
 * permissions and limitations under the License.
14
 */
15
16
/* $Id$ */
17
18
package org.apache.fop.layoutmgr;
19
20
import org.apache.fop.fo.Constants;
21
import org.apache.fop.fo.properties.KeepProperty;
22
import org.apache.fop.fo.properties.Property;
23
24
/**
25
 * Object representing a keep constraint, corresponding
26
 * to the XSL-FO <a href="http://www.w3.org/TR/xsl/#d0e26492">keep properties</a>.
27
 */
28
public class Keep {
29
30
    /** The integer value for "auto" keep strength. */
31
    private static final int STRENGTH_AUTO = Integer.MIN_VALUE;
32
33
    /** The integer value for "always" keep strength. */
34
    private static final int STRENGTH_ALWAYS = Integer.MAX_VALUE;
35
36
    public static final Keep KEEP_AUTO = new Keep(STRENGTH_AUTO, Constants.EN_AUTO);
37
38
    public static final Keep KEEP_ALWAYS = new Keep(STRENGTH_ALWAYS, Constants.EN_LINE);
39
40
    private int strength;
41
42
    private int context;
43
44
    private Keep(int strength, int context) {
45
        this.strength = strength;
46
        this.context = context;
47
    }
48
49
    private static int getKeepStrength(Property keep) {
50
        if (keep.isAuto()) {
51
            return STRENGTH_AUTO;
52
        } else if (keep.getEnum() == Constants.EN_ALWAYS) {
53
            return STRENGTH_ALWAYS;
54
        } else {
55
            return keep.getNumber().intValue();
56
        }
57
    }
58
59
    /**
60
     * Obtain a Keep instance corresponding to the given {@link KeepProperty}
61
     *
62
     * @param keepProperty  the {@link KeepProperty}
63
     * @return  a new instance corresponding to the given property
64
     */
65
    public static Keep getKeep(KeepProperty keepProperty) {
66
        Keep keep = new Keep(STRENGTH_AUTO, Constants.EN_AUTO);
67
        keep.update(keepProperty.getWithinPage(),   Constants.EN_PAGE);
68
        keep.update(keepProperty.getWithinColumn(), Constants.EN_COLUMN);
69
        keep.update(keepProperty.getWithinLine(),   Constants.EN_LINE);
70
        return keep;
71
    }
72
73
    private void update(Property keep, int context) {
74
        if (!keep.isAuto()) {
75
            this.strength = getKeepStrength(keep);
76
            this.context = context;
77
        }
78
    }
79
80
    /** @return {@code true} if the keep property was specified as "auto" */
81
    public boolean isAuto() {
82
        return strength == STRENGTH_AUTO;
83
    }
84
85
    /**
86
     * Returns the context of this keep.
87
     *
88
     * @return one of {@link Constants#EN_LINE}, {@link Constants#EN_COLUMN} or
89
     * {@link Constants#EN_PAGE}
90
     */
91
    public int getContext() {
92
        return context;
93
    }
94
95
    /** @return the penalty value corresponding to the strength of this Keep */
96
    public int getPenalty() {
97
        if (strength == STRENGTH_AUTO) {
98
            return 0;
99
        } else if (strength == STRENGTH_ALWAYS) {
100
            return KnuthElement.INFINITE;
101
        } else {
102
            return KnuthElement.INFINITE - 1;
103
        }
104
    }
105
106
    private static int getKeepContextPriority(int context) {
107
        switch (context) {
108
        case Constants.EN_LINE:   return 0;
109
        case Constants.EN_COLUMN: return 1;
110
        case Constants.EN_PAGE:   return 2;
111
        case Constants.EN_AUTO:   return 3;
112
        default: throw new IllegalArgumentException();
113
        }
114
    }
115
116
    /**
117
     * Compare this Keep instance to another one, and return the
118
     * stronger one if the context is the same
119
     *
120
     * @param other     the instance to compare to
121
     * @return  the winning Keep instance
122
     */
123
    public Keep compare(Keep other) {
124
125
        /* check strength "always" first, regardless of priority */
126
        if (this.strength == STRENGTH_ALWAYS
127
                && this.strength > other.strength) {
128
            return this;
129
        } else if (other.strength == STRENGTH_ALWAYS
130
                && other.strength > this.strength) {
131
            return other;
132
        }
133
134
        int pThis = getKeepContextPriority(this.context);
135
        int pOther = getKeepContextPriority(other.context);
136
137
        /* equal priority: strongest wins */
138
        if (pThis == pOther) {
139
            return (strength >= other.strength) ? this : other;
140
        }
141
142
        /* different priority: lowest priority wins */
143
        return (pThis < pOther) ? this : other;
144
    }
145
146
    /** {@inheritDoc} */
147
    public String toString() {
148
        return (strength == STRENGTH_AUTO) ? "auto"
149
                : (strength == STRENGTH_ALWAYS) ? "always"
150
                        : Integer.toString(strength);
151
    }
152
}
0
  + Id
153
  + Id
1
  + native
154
  + native
(-)src/java/org/apache/fop/layoutmgr/BlockContainerLayoutManager.java (-18 / +13 lines)
Lines 37-42 Link Here
37
import org.apache.fop.datatypes.Length;
37
import org.apache.fop.datatypes.Length;
38
import org.apache.fop.fo.flow.BlockContainer;
38
import org.apache.fop.fo.flow.BlockContainer;
39
import org.apache.fop.fo.properties.CommonAbsolutePosition;
39
import org.apache.fop.fo.properties.CommonAbsolutePosition;
40
import org.apache.fop.fo.properties.KeepProperty;
40
import org.apache.fop.traits.MinOptMax;
41
import org.apache.fop.traits.MinOptMax;
41
import org.apache.fop.traits.SpaceVal;
42
import org.apache.fop.traits.SpaceVal;
42
import org.apache.fop.util.ListUtil;
43
import org.apache.fop.util.ListUtil;
Lines 261-267 Link Here
261
262
262
        if (!firstVisibleMarkServed) {
263
        if (!firstVisibleMarkServed) {
263
            addKnuthElementsForSpaceBefore(returnList, alignment);
264
            addKnuthElementsForSpaceBefore(returnList, alignment);
264
            context.updateKeepWithPreviousPending(getKeepWithPreviousStrength());
265
            context.updateKeepWithPreviousPending(getKeepWithPrevious());
265
        }
266
        }
266
267
267
        addKnuthElementsForBorderPaddingBefore(returnList, !firstVisibleMarkServed);
268
        addKnuthElementsForBorderPaddingBefore(returnList, !firstVisibleMarkServed);
Lines 271-279 Link Here
271
            //Spaces, border and padding to be repeated at each break
272
            //Spaces, border and padding to be repeated at each break
272
            addPendingMarks(context);
273
            addPendingMarks(context);
273
274
274
            BlockLevelLayoutManager curLM; // currently active LM
275
            LayoutManager curLM; // currently active LM
275
            BlockLevelLayoutManager prevLM = null; // previously active LM
276
            LayoutManager prevLM = null; // previously active LM
276
            while ((curLM = (BlockLevelLayoutManager) getChildLM()) != null) {
277
            while ((curLM = getChildLM()) != null) {
277
                LayoutContext childLC = new LayoutContext(0);
278
                LayoutContext childLC = new LayoutContext(0);
278
                childLC.copyPendingMarksFrom(context);
279
                childLC.copyPendingMarksFrom(context);
279
                // curLM is a ?
280
                // curLM is a ?
Lines 323-330 Link Here
323
                        //Avoid NoSuchElementException below (happens with empty blocks)
324
                        //Avoid NoSuchElementException below (happens with empty blocks)
324
                        continue;
325
                        continue;
325
                    }
326
                    }
326
                    if (((ListElement) ListUtil.getLast(returnedList))
327
                    if (ElementListUtils.endsWithForcedBreak(returnedList)) {
327
                            .isForcedBreak()) {
328
                        // a descendant of this block has break-after
328
                        // a descendant of this block has break-after
329
                        if (curLM.isFinished()) {
329
                        if (curLM.isFinished()) {
330
                            // there is no other content in this block;
330
                            // there is no other content in this block;
Lines 391-397 Link Here
391
        context.clearPendingMarks();
391
        context.clearPendingMarks();
392
        addKnuthElementsForBreakAfter(returnList, context);
392
        addKnuthElementsForBreakAfter(returnList, context);
393
393
394
        context.updateKeepWithNextPending(getKeepWithNextStrength());
394
        context.updateKeepWithNextPending(getKeepWithNext());
395
395
396
        setFinished(true);
396
        setFinished(true);
397
        return returnList;
397
        return returnList;
Lines 1011-1033 Link Here
1011
    }
1011
    }
1012
1012
1013
    /** {@inheritDoc} */
1013
    /** {@inheritDoc} */
1014
    public int getKeepTogetherStrength() {
1014
    public KeepProperty getKeepTogetherProperty() {
1015
        int strength = KeepUtil.getCombinedBlockLevelKeepStrength(
1015
        return getBlockContainerFO().getKeepTogether();
1016
                getBlockContainerFO().getKeepTogether());
1017
        strength = Math.max(strength, getParentKeepTogetherStrength());
1018
        return strength;
1019
    }
1016
    }
1020
1017
1021
    /** {@inheritDoc} */
1018
    /** {@inheritDoc} */
1022
    public int getKeepWithNextStrength() {
1019
    public KeepProperty getKeepWithPreviousProperty() {
1023
        return KeepUtil.getCombinedBlockLevelKeepStrength(
1020
        return getBlockContainerFO().getKeepWithPrevious();
1024
                getBlockContainerFO().getKeepWithNext());
1025
    }
1021
    }
1026
1022
1027
    /** {@inheritDoc} */
1023
    /** {@inheritDoc} */
1028
    public int getKeepWithPreviousStrength() {
1024
    public KeepProperty getKeepWithNextProperty() {
1029
        return KeepUtil.getCombinedBlockLevelKeepStrength(
1025
        return getBlockContainerFO().getKeepWithNext();
1030
                getBlockContainerFO().getKeepWithPrevious());
1031
    }
1026
    }
1032
1027
1033
    /**
1028
    /**
(-)src/java/org/apache/fop/layoutmgr/BreakElement.java (-20 / +29 lines)
Lines 41-50 Link Here
41
     * @param context the layout context which contains the pending conditional elements
41
     * @param context the layout context which contains the pending conditional elements
42
     */
42
     */
43
    public BreakElement(Position position, int penaltyValue, LayoutContext context) {
43
    public BreakElement(Position position, int penaltyValue, LayoutContext context) {
44
        this(position, 0, penaltyValue, -1, context);
44
        this(position, penaltyValue, -1, context);
45
    }
45
    }
46
46
47
    /**
47
    /**
48
     * Create a new BreakElement for the given {@code position}, {@code penaltyValue}
49
     * and {@code breakClass}. (Used principally to generate break-possibilities in
50
     * ranges of content that must be kept together within the context corresponding
51
     * to the {@code breakClass}; expected to be one of {@link Constants#EN_AUTO},
52
     * {@link Constants#EN_LINE}, {@link Constants#EN_COLUMN} or {@link Constants#EN_PAGE})
53
     * @param position  the corresponding {@link Position}
54
     * @param penaltyValue  the penalty value
55
     * @param breakClass    the break class
56
     * @param context       the {@link LayoutContext}
57
     */
58
    public BreakElement(Position position, int penaltyValue, int breakClass, LayoutContext context) {
59
        this(position, 0, penaltyValue, breakClass, context);
60
    }
61
62
    /**
48
     * Constructor for hard breaks.
63
     * Constructor for hard breaks.
49
     *
64
     *
50
     * @param position the Position instance needed by the addAreas stage of the LMs.
65
     * @param position the Position instance needed by the addAreas stage of the LMs.
Lines 65-70 Link Here
65
        this.pendingAfterMarks = context.getPendingAfterMarks();
80
        this.pendingAfterMarks = context.getPendingAfterMarks();
66
    }
81
    }
67
82
83
    private static String getBreakClassName(int breakClass) {
84
        return AbstractBreaker.getBreakClassName(breakClass);
85
    }
86
68
    /** {@inheritDoc} */
87
    /** {@inheritDoc} */
69
    public boolean isConditional() {
88
    public boolean isConditional() {
70
        return false; //Does not really apply here
89
        return false; //Does not really apply here
Lines 143-169 Link Here
143
162
144
    /** {@inheritDoc} */
163
    /** {@inheritDoc} */
145
    public String toString() {
164
    public String toString() {
146
        StringBuffer sb = new StringBuffer();
165
        StringBuffer sb = new StringBuffer(64);
147
        sb.append("BreakPossibility[p:");
166
        sb.append("BreakPossibility[p:");
148
        sb.append(this.penaltyValue);
167
        sb.append(KnuthPenalty.valueOf(this.penaltyValue));
149
        if (isForcedBreak()) {
168
        if (isForcedBreak()) {
150
            sb.append(" (forced break");
169
            sb.append(" (forced break, ")
151
            switch (getBreakClass()) {
170
                    .append(getBreakClassName(this.breakClass))
152
            case Constants.EN_PAGE:
171
                    .append(")");
153
                sb.append(", page");
172
        } else if (this.penaltyValue >= 0 && this.breakClass != -1) {
154
                break;
173
            sb.append(" (keep constraint, ")
155
            case Constants.EN_COLUMN:
174
                    .append(getBreakClassName(this.breakClass))
156
                sb.append(", column");
175
                    .append(")");
157
                break;
158
            case Constants.EN_EVEN_PAGE:
159
                sb.append(", even page");
160
                break;
161
            case Constants.EN_ODD_PAGE:
162
                sb.append(", odd page");
163
                break;
164
            default:
165
            }
166
            sb.append(")");
167
        }
176
        }
168
        sb.append("; w:");
177
        sb.append("; w:");
169
        sb.append(penaltyWidth);
178
        sb.append(penaltyWidth);
(-)src/java/org/apache/fop/layoutmgr/FlowLayoutManager.java (-15 / +10 lines)
Lines 63-72 Link Here
63
    /** {@inheritDoc} */
63
    /** {@inheritDoc} */
64
    public List getNextKnuthElements(LayoutContext context, int alignment) {
64
    public List getNextKnuthElements(LayoutContext context, int alignment) {
65
65
66
        // set layout dimensions
67
        int flowIPD = getCurrentPV().getCurrentSpan().getColumnWidth();
68
        int flowBPD = getCurrentPV().getBodyRegion().getBPD();
69
70
        // currently active LM
66
        // currently active LM
71
        LayoutManager curLM;
67
        LayoutManager curLM;
72
        List returnedList;
68
        List returnedList;
Lines 84-95 Link Here
84
            int disableColumnBalancing = EN_FALSE;
80
            int disableColumnBalancing = EN_FALSE;
85
            if (curLM instanceof BlockLayoutManager) {
81
            if (curLM instanceof BlockLayoutManager) {
86
                span = ((BlockLayoutManager)curLM).getBlockFO().getSpan();
82
                span = ((BlockLayoutManager)curLM).getBlockFO().getSpan();
87
                disableColumnBalancing = ((BlockLayoutManager) curLM).getBlockFO()
83
                disableColumnBalancing = ((BlockLayoutManager) curLM).getBlockFO().getDisableColumnBalancing();
88
                        .getDisableColumnBalancing();
89
            } else if (curLM instanceof BlockContainerLayoutManager) {
84
            } else if (curLM instanceof BlockContainerLayoutManager) {
90
                span = ((BlockContainerLayoutManager)curLM).getBlockContainerFO().getSpan();
85
                span = ((BlockContainerLayoutManager)curLM).getBlockContainerFO().getSpan();
91
                disableColumnBalancing = ((BlockContainerLayoutManager) curLM).getBlockContainerFO()
86
                disableColumnBalancing = ((BlockContainerLayoutManager) curLM).getBlockContainerFO().getDisableColumnBalancing();
92
                        .getDisableColumnBalancing();
93
            }
87
            }
94
88
95
            int currentSpan = context.getCurrentSpan();
89
            int currentSpan = context.getCurrentSpan();
Lines 113-118 Link Here
113
107
114
            // get elements from curLM
108
            // get elements from curLM
115
            returnedList = curLM.getNextKnuthElements(childLC, alignment);
109
            returnedList = curLM.getNextKnuthElements(childLC, alignment);
110
            //int contentHeight = ElementListUtils.calcContentLength(returnedList);
116
            //log.debug("FLM.getNextKnuthElements> returnedList.size() = " + returnedList.size());
111
            //log.debug("FLM.getNextKnuthElements> returnedList.size() = " + returnedList.size());
117
            if (returnList.size() == 0 && childLC.isKeepWithPreviousPending()) {
112
            if (returnList.size() == 0 && childLC.isKeepWithPreviousPending()) {
118
                context.updateKeepWithPreviousPending(childLC.getKeepWithPreviousPending());
113
                context.updateKeepWithPreviousPending(childLC.getKeepWithPreviousPending());
Lines 154-160 Link Here
154
            context.updateKeepWithNextPending(childLC.getKeepWithNextPending());
149
            context.updateKeepWithNextPending(childLC.getKeepWithNextPending());
155
            childLC.clearKeepWithNextPending();
150
            childLC.clearKeepWithNextPending();
156
151
157
            context.updateKeepWithNextPending(getKeepWithNextStrength());
152
            context.updateKeepWithNextPending(getKeepWithNext());
158
        }
153
        }
159
154
160
        SpaceResolver.resolveElementList(returnList);
155
        SpaceResolver.resolveElementList(returnList);
Lines 203-220 Link Here
203
    }
198
    }
204
199
205
    /** {@inheritDoc} */
200
    /** {@inheritDoc} */
206
    public int getKeepTogetherStrength() {
201
    public Keep getKeepTogether() {
207
        return KEEP_AUTO;
202
        return Keep.KEEP_AUTO;
208
    }
203
    }
209
204
210
    /** {@inheritDoc} */
205
    /** {@inheritDoc} */
211
    public int getKeepWithNextStrength() {
206
    public Keep getKeepWithNext() {
212
        return KEEP_AUTO;
207
        return Keep.KEEP_AUTO;
213
    }
208
    }
214
209
215
    /** {@inheritDoc} */
210
    /** {@inheritDoc} */
216
    public int getKeepWithPreviousStrength() {
211
    public Keep getKeepWithPrevious() {
217
        return KEEP_AUTO;
212
        return Keep.KEEP_AUTO;
218
    }
213
    }
219
214
220
    /** {@inheritDoc} */
215
    /** {@inheritDoc} */
(-)src/java/org/apache/fop/layoutmgr/FootnoteBodyLayoutManager.java (-6 / +6 lines)
Lines 92-109 Link Here
92
    }
92
    }
93
93
94
    /** {@inheritDoc} */
94
    /** {@inheritDoc} */
95
    public int getKeepTogetherStrength() {
95
    public Keep getKeepTogether() {
96
        return getParentKeepTogetherStrength();
96
        return getParentKeepTogether();
97
    }
97
    }
98
98
99
    /** {@inheritDoc} */
99
    /** {@inheritDoc} */
100
    public int getKeepWithNextStrength() {
100
    public Keep getKeepWithNext() {
101
        return KEEP_AUTO;
101
        return Keep.KEEP_AUTO;
102
    }
102
    }
103
103
104
    /** {@inheritDoc} */
104
    /** {@inheritDoc} */
105
    public int getKeepWithPreviousStrength() {
105
    public Keep getKeepWithPrevious() {
106
        return KEEP_AUTO;
106
        return Keep.KEEP_AUTO;
107
    }
107
    }
108
108
109
}
109
}
(-)src/java/org/apache/fop/layoutmgr/BlockLayoutManager.java (-9 / +6 lines)
Lines 210-230 Link Here
210
    }
210
    }
211
211
212
    /** {@inheritDoc} */
212
    /** {@inheritDoc} */
213
    public int getKeepTogetherStrength() {
213
    public KeepProperty getKeepTogetherProperty() {
214
        KeepProperty keep = getBlockFO().getKeepTogether();
214
        return getBlockFO().getKeepTogether();
215
        int strength = KeepUtil.getCombinedBlockLevelKeepStrength(keep);
216
        strength = Math.max(strength, getParentKeepTogetherStrength());
217
        return strength;
218
    }
215
    }
219
216
220
    /** {@inheritDoc} */
217
    /** {@inheritDoc} */
221
    public int getKeepWithNextStrength() {
218
    public KeepProperty getKeepWithPreviousProperty() {
222
        return KeepUtil.getCombinedBlockLevelKeepStrength(getBlockFO().getKeepWithNext());
219
        return getBlockFO().getKeepWithPrevious();
223
    }
220
    }
224
221
225
    /** {@inheritDoc} */
222
    /** {@inheritDoc} */
226
    public int getKeepWithPreviousStrength() {
223
    public KeepProperty getKeepWithNextProperty() {
227
        return KeepUtil.getCombinedBlockLevelKeepStrength(getBlockFO().getKeepWithPrevious());
224
        return getBlockFO().getKeepWithNext();
228
    }
225
    }
229
226
230
    /** {@inheritDoc} */
227
    /** {@inheritDoc} */
(-)src/java/org/apache/fop/layoutmgr/PageBreaker.java (-21 / +26 lines)
Lines 443-451 Link Here
443
        pslm.getCurrentPV().getCurrentSpan().notifyFlowsFinished();
443
        pslm.getCurrentPV().getCurrentSpan().notifyFlowsFinished();
444
    }
444
    }
445
445
446
    /**
446
    /** @return the current child flow layout manager */
447
     * @return the current child flow layout manager
448
     */
449
    protected LayoutManager getCurrentChildLM() {
447
    protected LayoutManager getCurrentChildLM() {
450
        return childFLM;
448
        return childFLM;
451
    }
449
    }
Lines 464-508 Link Here
464
     */
462
     */
465
    private void handleBreakTrait(int breakVal) {
463
    private void handleBreakTrait(int breakVal) {
466
        Page curPage = pslm.getCurrentPage();
464
        Page curPage = pslm.getCurrentPage();
467
        if (breakVal == Constants.EN_ALL) {
465
        switch (breakVal) {
466
        case Constants.EN_ALL:
468
            //break due to span change in multi-column layout
467
            //break due to span change in multi-column layout
469
            curPage.getPageViewport().createSpan(true);
468
            curPage.getPageViewport().createSpan(true);
470
            return;
469
            return;
471
        } else if (breakVal == Constants.EN_NONE) {
470
        case Constants.EN_NONE:
472
            curPage.getPageViewport().createSpan(false);
471
            curPage.getPageViewport().createSpan(false);
473
            return;
472
            return;
474
        } else if (breakVal == Constants.EN_COLUMN
473
        case Constants.EN_COLUMN:
475
                || breakVal <= 0
474
        case Constants.EN_AUTO:
476
                || breakVal == Constants.EN_AUTO) {
475
        case Constants.EN_PAGE:
476
        case -1:
477
            PageViewport pv = curPage.getPageViewport();
477
            PageViewport pv = curPage.getPageViewport();
478
478
479
            //Check if previous page was spanned
479
            //Check if previous page was spanned
480
            boolean forceNewPageWithSpan = false;
480
            boolean forceNewPageWithSpan = false;
481
            RegionBody rb = (RegionBody)curPage.getSimplePageMaster().getRegion(
481
            RegionBody rb = (RegionBody)curPage.getSimplePageMaster().getRegion(
482
                    Constants.FO_REGION_BODY);
482
                    Constants.FO_REGION_BODY);
483
            if (rb.getColumnCount() > 1
483
            forceNewPageWithSpan
484
                    && pv.getCurrentSpan().getColumnCount() == 1) {
484
                    = (rb.getColumnCount() > 1
485
                forceNewPageWithSpan = true;
485
                        && pv.getCurrentSpan().getColumnCount() == 1);
486
            }
487
486
488
            if (forceNewPageWithSpan) {
487
            if (forceNewPageWithSpan) {
488
                log.trace("Forcing new page with span");
489
                curPage = pslm.makeNewPage(false, false);
489
                curPage = pslm.makeNewPage(false, false);
490
                curPage.getPageViewport().createSpan(true);
490
                curPage.getPageViewport().createSpan(true);
491
            } else if (pv.getCurrentSpan().hasMoreFlows()) {
491
            } else if (pv.getCurrentSpan().hasMoreFlows()) {
492
                log.trace("Moving to next flow");
492
                pv.getCurrentSpan().moveToNextFlow();
493
                pv.getCurrentSpan().moveToNextFlow();
493
            } else {
494
            } else {
494
                curPage = pslm.makeNewPage(false, false);
495
                log.trace("Making new page");
496
                /*curPage = */pslm.makeNewPage(false, false);
495
            }
497
            }
496
            return;
498
            return;
499
        default:
500
            log.debug("handling break-before after page " + pslm.getCurrentPageNum()
501
                + " breakVal=" + getBreakClassName(breakVal));
502
            if (needBlankPageBeforeNew(breakVal)) {
503
                log.trace("Inserting blank page");
504
                /*curPage = */pslm.makeNewPage(true, false);
505
            }
506
            if (needNewPage(breakVal)) {
507
                log.trace("Making new page");
508
                /*curPage = */pslm.makeNewPage(false, false);
509
            }
497
        }
510
        }
498
        log.debug("handling break-before after page " + pslm.getCurrentPageNum()
499
            + " breakVal=" + getBreakClassName(breakVal));
500
        if (needBlankPageBeforeNew(breakVal)) {
501
            curPage = pslm.makeNewPage(true, false);
502
        }
503
        if (needNewPage(breakVal)) {
504
            curPage = pslm.makeNewPage(false, false);
505
        }
506
    }
511
    }
507
512
508
    /**
513
    /**
(-)src/java/org/apache/fop/layoutmgr/PageBreakingAlgorithm.java (+142 lines)
Lines 190-195 Link Here
190
        footnoteElementIndex = -1;
190
        footnoteElementIndex = -1;
191
    }
191
    }
192
192
193
    private int currentKeepContext = Constants.EN_AUTO;
194
    private KnuthNode lastBeforeKeepContextSwitch;
195
196
    /**
197
     * {@inheritDoc}
198
     * Overridden to defer a part to the next page, if it
199
     * must be kept within one page, but is too large to fit in
200
     * the last column.
201
     */
202
    protected KnuthNode recoverFromTooLong(KnuthNode lastTooLong) {
203
204
        if (log.isDebugEnabled()) {
205
            log.debug("Recovering from too long: " + lastTooLong);
206
            log.debug("\tlastTooShort = " + getLastTooShort());
207
            log.debug("\tlastBeforeKeepContextSwitch = " + lastBeforeKeepContextSwitch);
208
            log.debug("\tcurrentKeepContext = " + AbstractBreaker.getBreakClassName(currentKeepContext));
209
        }
210
211
        if (lastBeforeKeepContextSwitch == null
212
                || currentKeepContext == Constants.EN_AUTO) {
213
            return super.recoverFromTooLong(lastTooLong);
214
        }
215
216
        KnuthNode node = lastBeforeKeepContextSwitch;
217
        lastBeforeKeepContextSwitch = null;
218
        // content would overflow, insert empty page/column(s) and try again
219
        while (!pageProvider.endPage(node.line - 1)) {
220
            log.trace("Adding node for empty column");
221
            node = createNode(
222
                    node.position,
223
                    node.line + 1, 1,
224
                    0, 0, 0,
225
                    0, 0, 0,
226
                    0, 0, node);
227
        }
228
        return node;
229
    }
230
231
    /**
232
     * Compare two KnuthNodes and return the node with the least demerit.
233
     *
234
     * @param node1 The first knuth node.
235
     * @param node2 The other knuth node.
236
     * @return the node with the least demerit.
237
     */
238
    protected KnuthNode compareNodes(KnuthNode node1, KnuthNode node2) {
239
240
        /* if either node is null, return the other one */
241
        if (node1 == null || node2 == null) {
242
            return (node1 == null) ? node2 : node1;
243
        }
244
245
        /* if either one of the nodes corresponds to a mere column-break,
246
         * and the other one corresponds to a page-break, return the page-break node
247
         */
248
        if (pageProvider != null) {
249
            if (pageProvider.endPage(node1.line - 1)
250
                    && !pageProvider.endPage(node2.line - 1)) {
251
                return node1;
252
            } else if (pageProvider.endPage(node2.line - 1)
253
                    && !pageProvider.endPage(node1.line - 1)) {
254
                return node2;
255
            }
256
        }
257
258
        /* all other cases: use superclass implementation */
259
        return super.compareNodes(node1, node2);
260
    }
261
193
    /** {@inheritDoc} */
262
    /** {@inheritDoc} */
194
    protected KnuthNode createNode(int position, int line, int fitness,
263
    protected KnuthNode createNode(int position, int line, int fitness,
195
                                   int totalWidth, int totalStretch, int totalShrink,
264
                                   int totalWidth, int totalStretch, int totalShrink,
Lines 234-239 Link Here
234
    }
303
    }
235
304
236
    /**
305
    /**
306
     * {@inheritDoc}
307
     * Overridden to consider penalties with value {@link KnuthElement#INFINITE}
308
     * as legal break-points, if the current keep-context allows this
309
     * (a keep-*.within-page="always" constraint still permits column-breaks)
310
     */
311
    protected void handlePenaltyAt(KnuthPenalty penalty, int position,
312
                                   int allowedBreaks) {
313
        super.handlePenaltyAt(penalty, position, allowedBreaks);
314
        /* if the penalty had value INFINITE, default implementation
315
         * will not have considered it a legal break, but it could still
316
         * be one.
317
         */
318
        if (penalty.getP() == KnuthPenalty.INFINITE) {
319
            int breakClass = penalty.getBreakClass();
320
            if (breakClass == Constants.EN_PAGE
321
                    || breakClass == Constants.EN_COLUMN) {
322
                considerLegalBreak(penalty, position);
323
            }
324
        }
325
    }
326
327
    /**
237
     * Handles the footnotes cited inside a block-level box. Updates footnotesList and the
328
     * Handles the footnotes cited inside a block-level box. Updates footnotesList and the
238
     * value of totalFootnotesLength with the lengths of the given footnotes.
329
     * value of totalFootnotesLength with the lengths of the given footnotes.
239
     * @param elementLists list of KnuthElement sequences corresponding to the footnotes
330
     * @param elementLists list of KnuthElement sequences corresponding to the footnotes
Lines 317-326 Link Here
317
408
318
    /** {@inheritDoc} */
409
    /** {@inheritDoc} */
319
    protected void considerLegalBreak(KnuthElement element, int elementIdx) {
410
    protected void considerLegalBreak(KnuthElement element, int elementIdx) {
411
        if (element.isPenalty()) {
412
            int breakClass = ((KnuthPenalty) element).getBreakClass();
413
            switch (breakClass) {
414
            case Constants.EN_PAGE:
415
            case Constants.EN_COLUMN:
416
                if (this.currentKeepContext != breakClass) {
417
                    this.lastBeforeKeepContextSwitch = getLastTooShort();
418
                }
419
                this.currentKeepContext = breakClass;
420
                break;
421
            case Constants.EN_AUTO:
422
                this.currentKeepContext = breakClass;
423
                break;
424
            default:
425
                //nop
426
            }
427
        }
320
        super.considerLegalBreak(element, elementIdx);
428
        super.considerLegalBreak(element, elementIdx);
321
        newFootnotes = false;
429
        newFootnotes = false;
322
    }
430
    }
323
431
432
    /** {@inheritDoc} */
433
    protected boolean elementCanEndLine(KnuthElement element, int line, int difference) {
434
        if (!(element.isPenalty()) || pageProvider == null) {
435
            return true;
436
        } else {
437
            KnuthPenalty p = (KnuthPenalty) element;
438
            if (p.getP() <= 0) {
439
                return true;
440
            } else {
441
                int context = p.getBreakClass();
442
                switch (context) {
443
                case Constants.EN_LINE:
444
                case Constants.EN_COLUMN:
445
                    return p.getP() < KnuthPenalty.INFINITE;
446
                case Constants.EN_PAGE:
447
                    return p.getP() < KnuthPenalty.INFINITE
448
                            || !pageProvider.endPage(line - 1)
449
                            || difference < 0;
450
                case Constants.EN_AUTO:
451
                    log.warn("keep is not auto but context is");
452
                    return true;
453
                default:
454
                    if (p.getP() < KnuthPenalty.INFINITE) {
455
                        log.warn("Non recognized keep context:" + context);
456
                        return true;
457
                    } else {
458
                        return false;
459
                    }
460
                }
461
            }
462
        }
463
    }
464
465
    /** {@inheritDoc} */
324
    protected int computeDifference(KnuthNode activeNode, KnuthElement element,
466
    protected int computeDifference(KnuthNode activeNode, KnuthElement element,
325
                                    int elementIndex) {
467
                                    int elementIndex) {
326
        KnuthPageNode pageNode = (KnuthPageNode) activeNode;
468
        KnuthPageNode pageNode = (KnuthPageNode) activeNode;
(-)src/java/org/apache/fop/layoutmgr/PageProvider.java (-1 / +44 lines)
Lines 146-152 Link Here
146
        return this.lastReportedBPD;
146
        return this.lastReportedBPD;
147
    }
147
    }
148
148
149
    // Wish there were a more elegant way to do this in Java
150
    private int[] getColIndexAndColCount(int index) {
151
        int columnCount = 0;
152
        int colIndex = startColumnOfCurrentElementList + index;
153
        int pageIndex = -1;
154
        do {
155
            colIndex -= columnCount;
156
            pageIndex++;
157
            Page page = getPage(false, pageIndex, RELTO_CURRENT_ELEMENT_LIST);
158
            columnCount = page.getPageViewport().getCurrentSpan().getColumnCount();
159
        } while (colIndex >= columnCount);
160
        return new int[] {colIndex, columnCount};
161
    }
162
149
    /**
163
    /**
164
     * Checks if a break at the passed index would start a new page
165
     * @param index the index of the element before the break
166
     * @return  {@code true} if the break starts a new page
167
     */
168
    boolean startPage(int index) {
169
        return getColIndexAndColCount(index)[0] == 0;
170
    }
171
172
    /**
173
     * Checks if a break at the passed index would end a page
174
     * @param index the index of the element before the break
175
     * @return  {@code true} if the break ends a page
176
     */
177
    boolean endPage(int index) {
178
        int[] colIndexAndColCount = getColIndexAndColCount(index);
179
        return colIndexAndColCount[0] == colIndexAndColCount[1] - 1;
180
    }
181
182
    /**
183
     * Obtain the applicable column-count for the element at the
184
     * passed index
185
     * @param index the index of the element
186
     * @return  the number of columns
187
     */
188
    int getColumnCount(int index) {
189
        return getColIndexAndColCount(index)[1];
190
    }
191
192
    /**
150
     * Returns the part index (0<x<partCount) which denotes the first part on the last page
193
     * Returns the part index (0<x<partCount) which denotes the first part on the last page
151
     * generated by the current element list.
194
     * generated by the current element list.
152
     * @param partCount Number of parts determined by the breaking algorithm
195
     * @param partCount Number of parts determined by the breaking algorithm
Lines 272-275 Link Here
272
        return page;
315
        return page;
273
    }
316
    }
274
317
275
}
318
}
(-)src/java/org/apache/fop/layoutmgr/list/ListBlockLayoutManager.java (-10 / +7 lines)
Lines 29-38 Link Here
29
import org.apache.fop.area.Area;
29
import org.apache.fop.area.Area;
30
import org.apache.fop.area.Block;
30
import org.apache.fop.area.Block;
31
import org.apache.fop.fo.flow.ListBlock;
31
import org.apache.fop.fo.flow.ListBlock;
32
import org.apache.fop.fo.properties.KeepProperty;
32
import org.apache.fop.layoutmgr.BlockStackingLayoutManager;
33
import org.apache.fop.layoutmgr.BlockStackingLayoutManager;
33
import org.apache.fop.layoutmgr.ConditionalElementListener;
34
import org.apache.fop.layoutmgr.ConditionalElementListener;
34
import org.apache.fop.layoutmgr.ElementListUtils;
35
import org.apache.fop.layoutmgr.ElementListUtils;
35
import org.apache.fop.layoutmgr.KeepUtil;
36
import org.apache.fop.layoutmgr.LayoutContext;
36
import org.apache.fop.layoutmgr.LayoutContext;
37
import org.apache.fop.layoutmgr.LayoutManager;
37
import org.apache.fop.layoutmgr.LayoutManager;
38
import org.apache.fop.layoutmgr.NonLeafPosition;
38
import org.apache.fop.layoutmgr.NonLeafPosition;
Lines 279-299 Link Here
279
    }
279
    }
280
280
281
    /** {@inheritDoc} */
281
    /** {@inheritDoc} */
282
    public int getKeepTogetherStrength() {
282
    public KeepProperty getKeepTogetherProperty() {
283
        int strength = KeepUtil.getCombinedBlockLevelKeepStrength(
283
        return getListBlockFO().getKeepTogether();
284
                getListBlockFO().getKeepTogether());
285
        strength = Math.max(strength, getParentKeepTogetherStrength());
286
        return strength;
287
    }
284
    }
288
285
289
    /** {@inheritDoc} */
286
    /** {@inheritDoc} */
290
    public int getKeepWithNextStrength() {
287
    public KeepProperty getKeepWithPreviousProperty() {
291
        return KeepUtil.getCombinedBlockLevelKeepStrength(getListBlockFO().getKeepWithNext());
288
        return getListBlockFO().getKeepWithPrevious();
292
    }
289
    }
293
290
294
    /** {@inheritDoc} */
291
    /** {@inheritDoc} */
295
    public int getKeepWithPreviousStrength() {
292
    public KeepProperty getKeepWithNextProperty() {
296
        return KeepUtil.getCombinedBlockLevelKeepStrength(getListBlockFO().getKeepWithPrevious());
293
        return getListBlockFO().getKeepWithNext();
297
    }
294
    }
298
295
299
    /** {@inheritDoc} */
296
    /** {@inheritDoc} */
(-)src/java/org/apache/fop/layoutmgr/list/ListItemLayoutManager.java (-23 / +19 lines)
Lines 32-44 Link Here
32
import org.apache.fop.fo.flow.ListItem;
32
import org.apache.fop.fo.flow.ListItem;
33
import org.apache.fop.fo.flow.ListItemBody;
33
import org.apache.fop.fo.flow.ListItemBody;
34
import org.apache.fop.fo.flow.ListItemLabel;
34
import org.apache.fop.fo.flow.ListItemLabel;
35
import org.apache.fop.layoutmgr.BlockLevelLayoutManager;
35
import org.apache.fop.fo.properties.KeepProperty;
36
import org.apache.fop.layoutmgr.BlockStackingLayoutManager;
36
import org.apache.fop.layoutmgr.BlockStackingLayoutManager;
37
import org.apache.fop.layoutmgr.BreakElement;
37
import org.apache.fop.layoutmgr.BreakElement;
38
import org.apache.fop.layoutmgr.ConditionalElementListener;
38
import org.apache.fop.layoutmgr.ConditionalElementListener;
39
import org.apache.fop.layoutmgr.ElementListObserver;
39
import org.apache.fop.layoutmgr.ElementListObserver;
40
import org.apache.fop.layoutmgr.ElementListUtils;
40
import org.apache.fop.layoutmgr.ElementListUtils;
41
import org.apache.fop.layoutmgr.KeepUtil;
41
import org.apache.fop.layoutmgr.Keep;
42
import org.apache.fop.layoutmgr.KnuthBlockBox;
42
import org.apache.fop.layoutmgr.KnuthBlockBox;
43
import org.apache.fop.layoutmgr.KnuthBox;
43
import org.apache.fop.layoutmgr.KnuthBox;
44
import org.apache.fop.layoutmgr.KnuthElement;
44
import org.apache.fop.layoutmgr.KnuthElement;
Lines 83-90 Link Here
83
    private MinOptMax effSpaceBefore;
83
    private MinOptMax effSpaceBefore;
84
    private MinOptMax effSpaceAfter;
84
    private MinOptMax effSpaceAfter;
85
85
86
    private int keepWithNextPendingOnLabel;
86
    private Keep keepWithNextPendingOnLabel;
87
    private int keepWithNextPendingOnBody;
87
    private Keep keepWithNextPendingOnBody;
88
88
89
    private int listItemHeight;
89
    private int listItemHeight;
90
90
Lines 254-261 Link Here
254
254
255
        context.updateKeepWithNextPending(this.keepWithNextPendingOnLabel);
255
        context.updateKeepWithNextPending(this.keepWithNextPendingOnLabel);
256
        context.updateKeepWithNextPending(this.keepWithNextPendingOnBody);
256
        context.updateKeepWithNextPending(this.keepWithNextPendingOnBody);
257
        context.updateKeepWithNextPending(getKeepWithNextStrength());
257
        context.updateKeepWithNextPending(getKeepWithNext());
258
        context.updateKeepWithPreviousPending(getKeepWithPreviousStrength());
258
        context.updateKeepWithPreviousPending(getKeepWithPrevious());
259
259
260
        setFinished(true);
260
        setFinished(true);
261
        resetSpaces();
261
        resetSpaces();
Lines 276-291 Link Here
276
        int totalHeight = Math.max(fullHeights[0], fullHeights[1]);
276
        int totalHeight = Math.max(fullHeights[0], fullHeights[1]);
277
        int step;
277
        int step;
278
        int addedBoxHeight = 0;
278
        int addedBoxHeight = 0;
279
        int keepWithNextActive = BlockLevelLayoutManager.KEEP_AUTO;
279
        Keep keepWithNextActive = Keep.KEEP_AUTO;
280
280
281
        LinkedList returnList = new LinkedList();
281
        LinkedList returnList = new LinkedList();
282
        while ((step = getNextStep(elementLists, start, end, partialHeights)) > 0) {
282
        while ((step = getNextStep(elementLists, start, end, partialHeights)) > 0) {
283
283
284
            if (end[0] + 1 == elementLists[0].size()) {
284
            if (end[0] + 1 == elementLists[0].size()) {
285
                keepWithNextActive = Math.max(keepWithNextActive, keepWithNextPendingOnLabel);
285
                keepWithNextActive = keepWithNextActive.compare(keepWithNextPendingOnLabel);
286
            }
286
            }
287
            if (end[1] + 1 == elementLists[1].size()) {
287
            if (end[1] + 1 == elementLists[1].size()) {
288
                keepWithNextActive = Math.max(keepWithNextActive, keepWithNextPendingOnBody);
288
                keepWithNextActive = keepWithNextActive.compare(keepWithNextPendingOnBody);
289
            }
289
            }
290
290
291
            // compute penalty height and box height
291
            // compute penalty height and box height
Lines 339-352 Link Here
339
            }
339
            }
340
340
341
            if (addedBoxHeight < totalHeight) {
341
            if (addedBoxHeight < totalHeight) {
342
                int strength = BlockLevelLayoutManager.KEEP_AUTO;
342
                Keep keep = keepWithNextActive.compare(getKeepTogether());
343
                strength = Math.max(strength, keepWithNextActive);
344
                strength = Math.max(strength, getKeepTogetherStrength());
345
                int p = stepPenalty;
343
                int p = stepPenalty;
346
                if (p > -KnuthElement.INFINITE) {
344
                if (p > -KnuthElement.INFINITE) {
347
                    p = Math.max(p, KeepUtil.getPenaltyForKeep(strength));
345
                    p = Math.max(p, keep.getPenalty());
348
                }
346
                }
349
                returnList.add(new BreakElement(stepPosition, penaltyHeight, p, -1, context));
347
                returnList.add(new BreakElement(stepPosition, penaltyHeight, p, keep.getContext(),
348
                        context));
350
            }
349
            }
351
        }
350
        }
352
351
Lines 644-664 Link Here
644
    }
643
    }
645
644
646
    /** {@inheritDoc} */
645
    /** {@inheritDoc} */
647
    public int getKeepTogetherStrength() {
646
    public KeepProperty getKeepTogetherProperty() {
648
        int strength = KeepUtil.getCombinedBlockLevelKeepStrength(
647
        return getListItemFO().getKeepTogether();
649
                getListItemFO().getKeepTogether());
650
        strength = Math.max(strength, getParentKeepTogetherStrength());
651
        return strength;
652
    }
648
    }
653
649
654
    /** {@inheritDoc} */
650
    /** {@inheritDoc} */
655
    public int getKeepWithNextStrength() {
651
    public KeepProperty getKeepWithPreviousProperty() {
656
        return KeepUtil.getCombinedBlockLevelKeepStrength(getListItemFO().getKeepWithNext());
652
        return getListItemFO().getKeepWithPrevious();
657
    }
653
    }
658
654
659
    /** {@inheritDoc} */
655
    /** {@inheritDoc} */
660
    public int getKeepWithPreviousStrength() {
656
    public KeepProperty getKeepWithNextProperty() {
661
        return KeepUtil.getCombinedBlockLevelKeepStrength(getListItemFO().getKeepWithPrevious());
657
        return getListItemFO().getKeepWithNext();
662
    }
658
    }
663
659
664
    /** {@inheritDoc} */
660
    /** {@inheritDoc} */
(-)src/java/org/apache/fop/layoutmgr/list/ListItemContentLayoutManager.java (-9 / +8 lines)
Lines 28-35 Link Here
28
import org.apache.fop.fo.flow.AbstractListItemPart;
28
import org.apache.fop.fo.flow.AbstractListItemPart;
29
import org.apache.fop.fo.flow.ListItemBody;
29
import org.apache.fop.fo.flow.ListItemBody;
30
import org.apache.fop.fo.flow.ListItemLabel;
30
import org.apache.fop.fo.flow.ListItemLabel;
31
import org.apache.fop.fo.properties.KeepProperty;
31
import org.apache.fop.layoutmgr.BlockStackingLayoutManager;
32
import org.apache.fop.layoutmgr.BlockStackingLayoutManager;
32
import org.apache.fop.layoutmgr.KeepUtil;
33
import org.apache.fop.layoutmgr.Keep;
33
import org.apache.fop.layoutmgr.LayoutContext;
34
import org.apache.fop.layoutmgr.LayoutContext;
34
import org.apache.fop.layoutmgr.LayoutManager;
35
import org.apache.fop.layoutmgr.LayoutManager;
35
import org.apache.fop.layoutmgr.NonLeafPosition;
36
import org.apache.fop.layoutmgr.NonLeafPosition;
Lines 221-240 Link Here
221
    }
222
    }
222
223
223
    /** {@inheritDoc} */
224
    /** {@inheritDoc} */
224
    public int getKeepTogetherStrength() {
225
    public KeepProperty getKeepTogetherProperty() {
225
        int strength = KeepUtil.getCombinedBlockLevelKeepStrength(getPartFO().getKeepTogether());
226
        return getPartFO().getKeepTogether();
226
        strength = Math.max(strength, getParentKeepTogetherStrength());
227
        return strength;
228
    }
227
    }
229
228
230
    /** {@inheritDoc} */
229
    /** {@inheritDoc} */
231
    public int getKeepWithNextStrength() {
230
    public Keep getKeepWithNext() {
232
        return KEEP_AUTO;
231
        return Keep.KEEP_AUTO;
233
    }
232
    }
234
233
235
    /** {@inheritDoc} */
234
    /** {@inheritDoc} */
236
    public int getKeepWithPreviousStrength() {
235
    public Keep getKeepWithPrevious() {
237
        return KEEP_AUTO;
236
        return Keep.KEEP_AUTO;
238
    }
237
    }
239
238
240
}
239
}
(-)src/java/org/apache/fop/layoutmgr/table/ActiveCell.java (-7 / +11 lines)
Lines 32-39 Link Here
32
import org.apache.fop.fo.flow.table.EffRow;
32
import org.apache.fop.fo.flow.table.EffRow;
33
import org.apache.fop.fo.flow.table.PrimaryGridUnit;
33
import org.apache.fop.fo.flow.table.PrimaryGridUnit;
34
import org.apache.fop.fo.properties.CommonBorderPaddingBackground;
34
import org.apache.fop.fo.properties.CommonBorderPaddingBackground;
35
import org.apache.fop.layoutmgr.BlockLevelLayoutManager;
36
import org.apache.fop.layoutmgr.ElementListUtils;
35
import org.apache.fop.layoutmgr.ElementListUtils;
36
import org.apache.fop.layoutmgr.Keep;
37
import org.apache.fop.layoutmgr.KnuthBlockBox;
37
import org.apache.fop.layoutmgr.KnuthBlockBox;
38
import org.apache.fop.layoutmgr.KnuthBox;
38
import org.apache.fop.layoutmgr.KnuthBox;
39
import org.apache.fop.layoutmgr.KnuthElement;
39
import org.apache.fop.layoutmgr.KnuthElement;
Lines 75-81 Link Here
75
    /** True if the next CellPart that will be created will be the last one for this cell. */
75
    /** True if the next CellPart that will be created will be the last one for this cell. */
76
    private boolean lastCellPart;
76
    private boolean lastCellPart;
77
77
78
    private int keepWithNextStrength;
78
    private Keep keepWithNext;
79
79
80
    private int spanIndex = 0;
80
    private int spanIndex = 0;
81
81
Lines 218-224 Link Here
218
        includedLength = -1;  // Avoid troubles with cells having content of zero length
218
        includedLength = -1;  // Avoid troubles with cells having content of zero length
219
        totalLength = previousRowsLength + ElementListUtils.calcContentLength(elementList);
219
        totalLength = previousRowsLength + ElementListUtils.calcContentLength(elementList);
220
        endRowIndex = rowIndex + pgu.getCell().getNumberRowsSpanned() - 1;
220
        endRowIndex = rowIndex + pgu.getCell().getNumberRowsSpanned() - 1;
221
        keepWithNextStrength = BlockLevelLayoutManager.KEEP_AUTO;
221
        keepWithNext = Keep.KEEP_AUTO;
222
        remainingLength = totalLength - previousRowsLength;
222
        remainingLength = totalLength - previousRowsLength;
223
223
224
        afterNextStep = new Step(previousRowsLength);
224
        afterNextStep = new Step(previousRowsLength);
Lines 314-320 Link Here
314
            KnuthElement el = (KnuthElement) knuthIter.next();
314
            KnuthElement el = (KnuthElement) knuthIter.next();
315
            if (el.isPenalty()) {
315
            if (el.isPenalty()) {
316
                prevIsBox = false;
316
                prevIsBox = false;
317
                if (el.getP() < KnuthElement.INFINITE) {
317
                if (el.getP() < KnuthElement.INFINITE
318
                        || ((KnuthPenalty) el).getBreakClass() == Constants.EN_PAGE) {
319
                    // TODO too much is being done in that test, only to handle
320
                    // keep.within-column properly.
321
318
                    // First legal break point
322
                    // First legal break point
319
                    breakFound = true;
323
                    breakFound = true;
320
                    KnuthPenalty p = (KnuthPenalty) el;
324
                    KnuthPenalty p = (KnuthPenalty) el;
Lines 533-539 Link Here
533
     */
537
     */
534
    CellPart createCellPart() {
538
    CellPart createCellPart() {
535
        if (nextStep.end + 1 == elementList.size()) {
539
        if (nextStep.end + 1 == elementList.size()) {
536
            keepWithNextStrength = pgu.getKeepWithNextStrength();
540
            keepWithNext = pgu.getKeepWithNext();
537
            // TODO if keep-with-next is set on the row, must every cell of the row
541
            // TODO if keep-with-next is set on the row, must every cell of the row
538
            // contribute some content from children blocks?
542
            // contribute some content from children blocks?
539
            // see http://mail-archives.apache.org/mod_mbox/xmlgraphics-fop-dev/200802.mbox/
543
            // see http://mail-archives.apache.org/mod_mbox/xmlgraphics-fop-dev/200802.mbox/
Lines 576-583 Link Here
576
        }
580
        }
577
    }
581
    }
578
582
579
    int getKeepWithNextStrength() {
583
    Keep getKeepWithNext() {
580
        return keepWithNextStrength;
584
        return keepWithNext;
581
    }
585
    }
582
586
583
    int getPenaltyValue() {
587
    int getPenaltyValue() {
(-)src/java/org/apache/fop/layoutmgr/table/TableContentLayoutManager.java (-11 / +10 lines)
Lines 35-44 Link Here
35
import org.apache.fop.fo.flow.table.PrimaryGridUnit;
35
import org.apache.fop.fo.flow.table.PrimaryGridUnit;
36
import org.apache.fop.fo.flow.table.Table;
36
import org.apache.fop.fo.flow.table.Table;
37
import org.apache.fop.fo.flow.table.TablePart;
37
import org.apache.fop.fo.flow.table.TablePart;
38
import org.apache.fop.layoutmgr.BlockLevelLayoutManager;
39
import org.apache.fop.layoutmgr.BreakElement;
38
import org.apache.fop.layoutmgr.BreakElement;
40
import org.apache.fop.layoutmgr.ElementListUtils;
39
import org.apache.fop.layoutmgr.ElementListUtils;
41
import org.apache.fop.layoutmgr.KeepUtil;
40
import org.apache.fop.layoutmgr.Keep;
42
import org.apache.fop.layoutmgr.KnuthBox;
41
import org.apache.fop.layoutmgr.KnuthBox;
43
import org.apache.fop.layoutmgr.KnuthElement;
42
import org.apache.fop.layoutmgr.KnuthElement;
44
import org.apache.fop.layoutmgr.KnuthGlue;
43
import org.apache.fop.layoutmgr.KnuthGlue;
Lines 213-225 Link Here
213
        context.clearKeepsPending();
212
        context.clearKeepsPending();
214
        context.setBreakBefore(Constants.EN_AUTO);
213
        context.setBreakBefore(Constants.EN_AUTO);
215
        context.setBreakAfter(Constants.EN_AUTO);
214
        context.setBreakAfter(Constants.EN_AUTO);
216
        int keepWithPrevious = BlockLevelLayoutManager.KEEP_AUTO;
215
        Keep keepWithPrevious = Keep.KEEP_AUTO;
217
        int breakBefore = Constants.EN_AUTO;
216
        int breakBefore = Constants.EN_AUTO;
218
        if (rowGroup != null) {
217
        if (rowGroup != null) {
219
            RowGroupLayoutManager rowGroupLM = new RowGroupLayoutManager(getTableLM(), rowGroup,
218
            RowGroupLayoutManager rowGroupLM = new RowGroupLayoutManager(getTableLM(), rowGroup,
220
                    stepper);
219
                    stepper);
221
            List nextRowGroupElems = rowGroupLM.getNextKnuthElements(context, alignment, bodyType);
220
            List nextRowGroupElems = rowGroupLM.getNextKnuthElements(context, alignment, bodyType);
222
            keepWithPrevious = Math.max(keepWithPrevious, context.getKeepWithPreviousPending());
221
            keepWithPrevious = keepWithPrevious.compare(context.getKeepWithPreviousPending());
223
            breakBefore = context.getBreakBefore();
222
            breakBefore = context.getBreakBefore();
224
            int breakBetween = context.getBreakAfter();
223
            int breakBetween = context.getBreakAfter();
225
            returnList.addAll(nextRowGroupElems);
224
            returnList.addAll(nextRowGroupElems);
Lines 228-234 Link Here
228
227
229
                //Note previous pending keep-with-next and clear the strength
228
                //Note previous pending keep-with-next and clear the strength
230
                //(as the layout context is reused)
229
                //(as the layout context is reused)
231
                int keepWithNextPending = context.getKeepWithNextPending();
230
                Keep keepWithNextPending = context.getKeepWithNextPending();
232
                context.clearKeepWithNextPending();
231
                context.clearKeepWithNextPending();
233
232
234
                //Get elements for next row group
233
                //Get elements for next row group
Lines 246-262 Link Here
246
                 */
245
                 */
247
246
248
                //Determine keep constraints
247
                //Determine keep constraints
249
                int penaltyStrength = BlockLevelLayoutManager.KEEP_AUTO;
248
                Keep keep = keepWithNextPending.compare(context.getKeepWithPreviousPending());
250
                penaltyStrength = Math.max(penaltyStrength, keepWithNextPending);
251
                penaltyStrength = Math.max(penaltyStrength, context.getKeepWithPreviousPending());
252
                context.clearKeepWithPreviousPending();
249
                context.clearKeepWithPreviousPending();
253
                penaltyStrength = Math.max(penaltyStrength, getTableLM().getKeepTogetherStrength());
250
                keep = keep.compare(getTableLM().getKeepTogether());
254
                int penaltyValue = KeepUtil.getPenaltyForKeep(penaltyStrength);
251
                int penaltyValue = keep.getPenalty();
252
                int breakClass = keep.getContext();
255
253
256
                breakBetween = BreakUtil.compareBreakClasses(breakBetween,
254
                breakBetween = BreakUtil.compareBreakClasses(breakBetween,
257
                        context.getBreakBefore());
255
                        context.getBreakBefore());
258
                if (breakBetween != Constants.EN_AUTO) {
256
                if (breakBetween != Constants.EN_AUTO) {
259
                    penaltyValue = -KnuthElement.INFINITE;
257
                    penaltyValue = -KnuthElement.INFINITE;
258
                    breakClass = breakBetween;
260
                }
259
                }
261
                BreakElement breakElement;
260
                BreakElement breakElement;
262
                ListIterator elemIter = returnList.listIterator(returnList.size());
261
                ListIterator elemIter = returnList.listIterator(returnList.size());
Lines 267-273 Link Here
267
                    breakElement = (BreakElement) elem;
266
                    breakElement = (BreakElement) elem;
268
                }
267
                }
269
                breakElement.setPenaltyValue(penaltyValue);
268
                breakElement.setPenaltyValue(penaltyValue);
270
                breakElement.setBreakClass(breakBetween);
269
                breakElement.setBreakClass(breakClass);
271
                returnList.addAll(nextRowGroupElems);
270
                returnList.addAll(nextRowGroupElems);
272
                breakBetween = context.getBreakAfter();
271
                breakBetween = context.getBreakAfter();
273
            }
272
            }
(-)src/java/org/apache/fop/layoutmgr/table/RowGroupLayoutManager.java (-2 / +2 lines)
Lines 60-67 Link Here
60
        LinkedList returnList = new LinkedList();
60
        LinkedList returnList = new LinkedList();
61
        createElementsForRowGroup(context, alignment, bodyType, returnList);
61
        createElementsForRowGroup(context, alignment, bodyType, returnList);
62
62
63
        context.updateKeepWithPreviousPending(rowGroup[0].getKeepWithPreviousStrength());
63
        context.updateKeepWithPreviousPending(rowGroup[0].getKeepWithPrevious());
64
        context.updateKeepWithNextPending(rowGroup[rowGroup.length - 1].getKeepWithNextStrength());
64
        context.updateKeepWithNextPending(rowGroup[rowGroup.length - 1].getKeepWithNext());
65
65
66
        int breakBefore = Constants.EN_AUTO;
66
        int breakBefore = Constants.EN_AUTO;
67
        TableRow firstRow = rowGroup[0].getTableRow();
67
        TableRow firstRow = rowGroup[0].getTableRow();
(-)src/java/org/apache/fop/layoutmgr/table/TableLayoutManager.java (-11 / +9 lines)
Lines 35-45 Link Here
35
import org.apache.fop.fo.FObj;
35
import org.apache.fop.fo.FObj;
36
import org.apache.fop.fo.flow.table.Table;
36
import org.apache.fop.fo.flow.table.Table;
37
import org.apache.fop.fo.flow.table.TableColumn;
37
import org.apache.fop.fo.flow.table.TableColumn;
38
import org.apache.fop.fo.properties.KeepProperty;
38
import org.apache.fop.layoutmgr.BlockLevelEventProducer;
39
import org.apache.fop.layoutmgr.BlockLevelEventProducer;
39
import org.apache.fop.layoutmgr.BlockStackingLayoutManager;
40
import org.apache.fop.layoutmgr.BlockStackingLayoutManager;
40
import org.apache.fop.layoutmgr.BreakElement;
41
import org.apache.fop.layoutmgr.BreakElement;
41
import org.apache.fop.layoutmgr.ConditionalElementListener;
42
import org.apache.fop.layoutmgr.ConditionalElementListener;
42
import org.apache.fop.layoutmgr.KeepUtil;
43
import org.apache.fop.layoutmgr.KnuthElement;
43
import org.apache.fop.layoutmgr.KnuthElement;
44
import org.apache.fop.layoutmgr.KnuthGlue;
44
import org.apache.fop.layoutmgr.KnuthGlue;
45
import org.apache.fop.layoutmgr.LayoutContext;
45
import org.apache.fop.layoutmgr.LayoutContext;
Lines 256-265 Link Here
256
        log.debug(contentKnuthElements);
256
        log.debug(contentKnuthElements);
257
        wrapPositionElements(contentKnuthElements, returnList);
257
        wrapPositionElements(contentKnuthElements, returnList);
258
258
259
        context.updateKeepWithPreviousPending(getKeepWithPreviousStrength());
259
        context.updateKeepWithPreviousPending(getKeepWithPrevious());
260
        context.updateKeepWithPreviousPending(childLC.getKeepWithPreviousPending());
260
        context.updateKeepWithPreviousPending(childLC.getKeepWithPreviousPending());
261
261
262
        context.updateKeepWithNextPending(getKeepWithNextStrength());
262
        context.updateKeepWithNextPending(getKeepWithNext());
263
        context.updateKeepWithNextPending(childLC.getKeepWithNextPending());
263
        context.updateKeepWithNextPending(childLC.getKeepWithNextPending());
264
264
265
        if (getTable().isSeparateBorderModel()) {
265
        if (getTable().isSeparateBorderModel()) {
Lines 448-467 Link Here
448
    }
448
    }
449
449
450
    /** {@inheritDoc} */
450
    /** {@inheritDoc} */
451
    public int getKeepTogetherStrength() {
451
    public KeepProperty getKeepTogetherProperty() {
452
        int strength = KeepUtil.getCombinedBlockLevelKeepStrength(getTable().getKeepTogether());
452
        return getTable().getKeepTogether();
453
        strength = Math.max(strength, getParentKeepTogetherStrength());
454
        return strength;
455
    }
453
    }
456
454
457
    /** {@inheritDoc} */
455
    /** {@inheritDoc} */
458
    public int getKeepWithNextStrength() {
456
    public KeepProperty getKeepWithPreviousProperty() {
459
        return KeepUtil.getCombinedBlockLevelKeepStrength(getTable().getKeepWithNext());
457
        return getTable().getKeepWithPrevious();
460
    }
458
    }
461
459
462
    /** {@inheritDoc} */
460
    /** {@inheritDoc} */
463
    public int getKeepWithPreviousStrength() {
461
    public KeepProperty getKeepWithNextProperty() {
464
        return KeepUtil.getCombinedBlockLevelKeepStrength(getTable().getKeepWithPrevious());
462
        return getTable().getKeepWithNext();
465
    }
463
    }
466
464
467
    // --------- Property Resolution related functions --------- //
465
    // --------- Property Resolution related functions --------- //
(-)src/java/org/apache/fop/layoutmgr/table/TableCellLayoutManager.java (-21 / +22 lines)
Lines 24-29 Link Here
24
24
25
import org.apache.commons.logging.Log;
25
import org.apache.commons.logging.Log;
26
import org.apache.commons.logging.LogFactory;
26
import org.apache.commons.logging.LogFactory;
27
27
import org.apache.fop.area.Area;
28
import org.apache.fop.area.Area;
28
import org.apache.fop.area.Block;
29
import org.apache.fop.area.Block;
29
import org.apache.fop.area.Trait;
30
import org.apache.fop.area.Trait;
Lines 31-51 Link Here
31
import org.apache.fop.fo.flow.table.GridUnit;
32
import org.apache.fop.fo.flow.table.GridUnit;
32
import org.apache.fop.fo.flow.table.PrimaryGridUnit;
33
import org.apache.fop.fo.flow.table.PrimaryGridUnit;
33
import org.apache.fop.fo.flow.table.Table;
34
import org.apache.fop.fo.flow.table.Table;
34
import org.apache.fop.fo.flow.table.TablePart;
35
import org.apache.fop.fo.flow.table.TableCell;
35
import org.apache.fop.fo.flow.table.TableCell;
36
import org.apache.fop.fo.flow.table.TableColumn;
36
import org.apache.fop.fo.flow.table.TableColumn;
37
import org.apache.fop.fo.flow.table.TablePart;
37
import org.apache.fop.fo.flow.table.TableRow;
38
import org.apache.fop.fo.flow.table.TableRow;
38
import org.apache.fop.fo.properties.CommonBorderPaddingBackground;
39
import org.apache.fop.fo.properties.CommonBorderPaddingBackground;
39
import org.apache.fop.fo.properties.CommonBorderPaddingBackground.BorderInfo;
40
import org.apache.fop.fo.properties.CommonBorderPaddingBackground.BorderInfo;
40
import org.apache.fop.layoutmgr.AreaAdditionUtil;
41
import org.apache.fop.layoutmgr.AreaAdditionUtil;
41
import org.apache.fop.layoutmgr.BlockLevelLayoutManager;
42
import org.apache.fop.layoutmgr.BlockLevelLayoutManager;
42
import org.apache.fop.layoutmgr.BlockStackingLayoutManager;
43
import org.apache.fop.layoutmgr.BlockStackingLayoutManager;
43
import org.apache.fop.layoutmgr.KeepUtil;
44
import org.apache.fop.layoutmgr.ElementListUtils;
45
import org.apache.fop.layoutmgr.Keep;
44
import org.apache.fop.layoutmgr.KnuthBox;
46
import org.apache.fop.layoutmgr.KnuthBox;
45
import org.apache.fop.layoutmgr.KnuthElement;
47
import org.apache.fop.layoutmgr.KnuthElement;
46
import org.apache.fop.layoutmgr.KnuthGlue;
48
import org.apache.fop.layoutmgr.KnuthGlue;
47
import org.apache.fop.layoutmgr.KnuthPenalty;
49
import org.apache.fop.layoutmgr.KnuthPenalty;
48
import org.apache.fop.layoutmgr.LayoutContext;
50
import org.apache.fop.layoutmgr.LayoutContext;
51
import org.apache.fop.layoutmgr.LayoutManager;
49
import org.apache.fop.layoutmgr.Position;
52
import org.apache.fop.layoutmgr.Position;
50
import org.apache.fop.layoutmgr.PositionIterator;
53
import org.apache.fop.layoutmgr.PositionIterator;
51
import org.apache.fop.layoutmgr.SpaceResolver;
54
import org.apache.fop.layoutmgr.SpaceResolver;
Lines 138-146 Link Here
138
        List contentList = new LinkedList();
141
        List contentList = new LinkedList();
139
        List returnList = new LinkedList();
142
        List returnList = new LinkedList();
140
143
141
        BlockLevelLayoutManager curLM; // currently active LM
144
        LayoutManager curLM; // currently active LM
142
        BlockLevelLayoutManager prevLM = null; // previously active LM
145
        LayoutManager prevLM = null; // previously active LM
143
        while ((curLM = (BlockLevelLayoutManager) getChildLM()) != null) {
146
        while ((curLM = getChildLM()) != null) {
144
            LayoutContext childLC = new LayoutContext(0);
147
            LayoutContext childLC = new LayoutContext(0);
145
            // curLM is a ?
148
            // curLM is a ?
146
            childLC.setStackLimitBP(MinOptMax.subtract(context
149
            childLC.setStackLimitBP(MinOptMax.subtract(context
Lines 153-163 Link Here
153
                log.debug("child LM signals pending keep with next");
156
                log.debug("child LM signals pending keep with next");
154
            }
157
            }
155
            if (contentList.isEmpty() && childLC.isKeepWithPreviousPending()) {
158
            if (contentList.isEmpty() && childLC.isKeepWithPreviousPending()) {
156
                primaryGridUnit.setKeepWithPreviousStrength(childLC.getKeepWithPreviousPending());
159
                primaryGridUnit.setKeepWithPrevious(childLC.getKeepWithPreviousPending());
157
                childLC.clearKeepWithPreviousPending();
160
                childLC.clearKeepWithPreviousPending();
158
            }
161
            }
159
162
160
            if (prevLM != null) {
163
            if (prevLM != null
164
                    && !ElementListUtils.endsWithForcedBreak(contentList)) {
161
                // there is a block handled by prevLM
165
                // there is a block handled by prevLM
162
                // before the one handled by curLM
166
                // before the one handled by curLM
163
                addInBetweenBreak(contentList, context, childLC);
167
                addInBetweenBreak(contentList, context, childLC);
Lines 174-180 Link Here
174
            }
178
            }
175
            prevLM = curLM;
179
            prevLM = curLM;
176
        }
180
        }
177
        primaryGridUnit.setKeepWithNextStrength(context.getKeepWithNextPending());
181
        primaryGridUnit.setKeepWithNext(context.getKeepWithNextPending());
178
182
179
        returnedList = new LinkedList();
183
        returnedList = new LinkedList();
180
        if (!contentList.isEmpty()) {
184
        if (!contentList.isEmpty()) {
Lines 195-201 Link Here
195
        }
199
        }
196
        final KnuthElement lastItem = (KnuthElement) ListUtil
200
        final KnuthElement lastItem = (KnuthElement) ListUtil
197
                .getLast(returnList);
201
                .getLast(returnList);
198
        if (((KnuthElement) lastItem).isForcedBreak()) {
202
        if (lastItem.isForcedBreak()) {
199
            KnuthPenalty p = (KnuthPenalty) lastItem;
203
            KnuthPenalty p = (KnuthPenalty) lastItem;
200
            primaryGridUnit.setBreakAfter(p.getBreakClass());
204
            primaryGridUnit.setBreakAfter(p.getBreakClass());
201
            p.setP(0);
205
            p.setP(0);
Lines 556-581 Link Here
556
    }
560
    }
557
561
558
    /** {@inheritDoc} */
562
    /** {@inheritDoc} */
559
    public int getKeepTogetherStrength() {
563
    public Keep getKeepTogether() {
560
        int strength = KEEP_AUTO;
564
        Keep keep = Keep.KEEP_AUTO;
561
        if (primaryGridUnit.getRow() != null) {
565
        if (primaryGridUnit.getRow() != null) {
562
            strength = Math.max(strength, KeepUtil.getKeepStrength(
566
            keep = Keep.getKeep(primaryGridUnit.getRow().getKeepTogether());
563
                    primaryGridUnit.getRow().getKeepTogether().getWithinPage()));
564
            strength = Math.max(strength, KeepUtil.getKeepStrength(
565
                    primaryGridUnit.getRow().getKeepTogether().getWithinColumn()));
566
        }
567
        }
567
        strength = Math.max(strength, getParentKeepTogetherStrength());
568
        keep = keep.compare(getParentKeepTogether());
568
        return strength;
569
        return keep;
569
    }
570
    }
570
571
571
    /** {@inheritDoc} */
572
    /** {@inheritDoc} */
572
    public int getKeepWithNextStrength() {
573
    public Keep getKeepWithNext() {
573
        return KEEP_AUTO; //TODO FIX ME (table-cell has no keep-with-next!)
574
        return Keep.KEEP_AUTO; //TODO FIX ME (table-cell has no keep-with-next!)
574
    }
575
    }
575
576
576
    /** {@inheritDoc} */
577
    /** {@inheritDoc} */
577
    public int getKeepWithPreviousStrength() {
578
    public Keep getKeepWithPrevious() {
578
        return KEEP_AUTO; //TODO FIX ME (table-cell has no keep-with-previous!)
579
        return Keep.KEEP_AUTO; //TODO FIX ME (table-cell has no keep-with-previous!)
579
    }
580
    }
580
581
581
    // --------- Property Resolution related functions --------- //
582
    // --------- Property Resolution related functions --------- //
(-)src/java/org/apache/fop/layoutmgr/table/TableAndCaptionLayoutManager.java (-16 / +6 lines)
Lines 23-28 Link Here
23
import org.apache.fop.area.Block;
23
import org.apache.fop.area.Block;
24
import org.apache.fop.fo.flow.table.TableAndCaption;
24
import org.apache.fop.fo.flow.table.TableAndCaption;
25
import org.apache.fop.layoutmgr.BlockStackingLayoutManager;
25
import org.apache.fop.layoutmgr.BlockStackingLayoutManager;
26
import org.apache.fop.layoutmgr.Keep;
26
import org.apache.fop.layoutmgr.LayoutContext;
27
import org.apache.fop.layoutmgr.LayoutContext;
27
import org.apache.fop.layoutmgr.PositionIterator;
28
import org.apache.fop.layoutmgr.PositionIterator;
28
29
Lines 201-232 Link Here
201
    }
202
    }
202
203
203
    /** {@inheritDoc} */
204
    /** {@inheritDoc} */
204
    public int getKeepTogetherStrength() {
205
    public Keep getKeepWithNext() {
205
        int strength = KEEP_AUTO;
206
        return Keep.KEEP_AUTO;
206
        /* TODO Complete me!
207
        /* TODO Complete me!
207
        int strength = KeepUtil.getCombinedBlockLevelKeepStrength(
208
                getTableAndCaptionFO().getKeepTogether());
209
        */
210
        strength = Math.max(strength, getParentKeepTogetherStrength());
211
        return strength;
212
    }
213
214
    /** {@inheritDoc} */
215
    public int getKeepWithNextStrength() {
216
        return KEEP_AUTO;
217
        /* TODO Complete me!
218
        return KeepUtil.getCombinedBlockLevelKeepStrength(
208
        return KeepUtil.getCombinedBlockLevelKeepStrength(
219
                getTableAndCaptionFO().getKeepWithNext());
209
                getTableAndCaptionFO().getKeepWithNext());
220
        */
210
        */
221
    }
211
    }
222
212
223
    /** {@inheritDoc} */
213
    /** {@inheritDoc} */
224
    public int getKeepWithPreviousStrength() {
214
    public Keep getKeepWithPrevious() {
225
        return KEEP_AUTO;
215
        return Keep.KEEP_AUTO;
226
        /* TODO Complete me!
216
        /* TODO Complete me!
227
        return KeepUtil.getCombinedBlockLevelKeepStrength(
217
        return KeepUtil.getCombinedBlockLevelKeepStrength(
228
                getTableAndCaptionFO().getKeepWithPrevious());
218
                getTableAndCaptionFO().getKeepWithPrevious());
229
        */
219
        */
230
    }
220
    }
231
221
232
}
222
}
(-)src/java/org/apache/fop/layoutmgr/table/TableStepper.java (-16 / +12 lines)
Lines 30-41 Link Here
30
import org.apache.fop.fo.flow.table.EffRow;
30
import org.apache.fop.fo.flow.table.EffRow;
31
import org.apache.fop.fo.flow.table.GridUnit;
31
import org.apache.fop.fo.flow.table.GridUnit;
32
import org.apache.fop.fo.flow.table.PrimaryGridUnit;
32
import org.apache.fop.fo.flow.table.PrimaryGridUnit;
33
import org.apache.fop.layoutmgr.BlockLevelLayoutManager;
34
import org.apache.fop.layoutmgr.BreakElement;
33
import org.apache.fop.layoutmgr.BreakElement;
35
import org.apache.fop.layoutmgr.KeepUtil;
34
import org.apache.fop.layoutmgr.Keep;
36
import org.apache.fop.layoutmgr.KnuthBlockBox;
35
import org.apache.fop.layoutmgr.KnuthBlockBox;
37
import org.apache.fop.layoutmgr.KnuthBox;
36
import org.apache.fop.layoutmgr.KnuthBox;
38
import org.apache.fop.layoutmgr.KnuthElement;
39
import org.apache.fop.layoutmgr.KnuthGlue;
37
import org.apache.fop.layoutmgr.KnuthGlue;
40
import org.apache.fop.layoutmgr.KnuthPenalty;
38
import org.apache.fop.layoutmgr.KnuthPenalty;
41
import org.apache.fop.layoutmgr.LayoutContext;
39
import org.apache.fop.layoutmgr.LayoutContext;
Lines 241-280 Link Here
241
                }
239
                }
242
            }
240
            }
243
241
244
            int strength = BlockLevelLayoutManager.KEEP_AUTO;
242
            Keep keep = Keep.KEEP_AUTO;
245
            int stepPenalty = 0;
243
            int stepPenalty = 0;
246
            for (Iterator iter = activeCells.iterator(); iter.hasNext();) {
244
            for (Iterator iter = activeCells.iterator(); iter.hasNext();) {
247
                ActiveCell activeCell = (ActiveCell) iter.next();
245
                ActiveCell activeCell = (ActiveCell) iter.next();
248
                strength = Math.max(strength, activeCell.getKeepWithNextStrength());
246
                keep = keep.compare(activeCell.getKeepWithNext());
249
                stepPenalty = Math.max(stepPenalty, activeCell.getPenaltyValue());
247
                stepPenalty = Math.max(stepPenalty, activeCell.getPenaltyValue());
250
            }
248
            }
251
            if (!rowFinished) {
249
            if (!rowFinished) {
252
                strength = Math.max(strength, rowGroup[activeRowIndex].getKeepTogetherStrength());
250
                keep = keep.compare(rowGroup[activeRowIndex].getKeepTogether());
253
                //The above call doesn't take the penalty from the table into account, so...
251
                //The above call doesn't take the penalty from the table into account, so...
254
                strength = Math.max(strength, getTableLM().getKeepTogetherStrength());
252
                keep = keep.compare(getTableLM().getKeepTogether());
255
            } else if (activeRowIndex < rowGroup.length - 1) {
253
            } else if (activeRowIndex < rowGroup.length - 1) {
256
                strength = Math.max(strength,
254
                keep = keep.compare(rowGroup[activeRowIndex].getKeepWithNext());
257
                        rowGroup[activeRowIndex].getKeepWithNextStrength());
255
                keep = keep.compare(rowGroup[activeRowIndex + 1].getKeepWithPrevious());
258
                strength = Math.max(strength,
259
                        rowGroup[activeRowIndex + 1].getKeepWithPreviousStrength());
260
                nextBreakClass = BreakUtil.compareBreakClasses(nextBreakClass,
256
                nextBreakClass = BreakUtil.compareBreakClasses(nextBreakClass,
261
                        rowGroup[activeRowIndex].getBreakAfter());
257
                        rowGroup[activeRowIndex].getBreakAfter());
262
                nextBreakClass = BreakUtil.compareBreakClasses(nextBreakClass,
258
                nextBreakClass = BreakUtil.compareBreakClasses(nextBreakClass,
263
                        rowGroup[activeRowIndex + 1].getBreakBefore());
259
                        rowGroup[activeRowIndex + 1].getBreakBefore());
264
            }
260
            }
265
            int p = KeepUtil.getPenaltyForKeep(strength);
261
            int p = keep.getPenalty();
266
            if (rowHeightSmallerThanFirstStep) {
262
            if (rowHeightSmallerThanFirstStep) {
267
                rowHeightSmallerThanFirstStep = false;
263
                rowHeightSmallerThanFirstStep = false;
268
                p = KnuthPenalty.INFINITE;
264
                p = KnuthPenalty.INFINITE;
269
            }
265
            }
270
            if (p > -KnuthElement.INFINITE) {
266
            p = Math.max(p, stepPenalty);
271
                p = Math.max(p, stepPenalty);
267
            int breakClass = keep.getContext();
272
            }
273
            if (nextBreakClass != Constants.EN_AUTO) {
268
            if (nextBreakClass != Constants.EN_AUTO) {
274
                log.trace("Forced break encountered");
269
                log.trace("Forced break encountered");
275
                p = -KnuthPenalty.INFINITE; //Overrides any keeps (see 4.8 in XSL 1.0)
270
                p = -KnuthPenalty.INFINITE; //Overrides any keeps (see 4.8 in XSL 1.0)
271
                breakClass = nextBreakClass;
276
            }
272
            }
277
            returnList.add(new BreakElement(penaltyPos, effPenaltyLen, p, nextBreakClass, context));
273
            returnList.add(new BreakElement(penaltyPos, effPenaltyLen, p, breakClass, context));
278
            if (penaltyOrGlueLen < 0) {
274
            if (penaltyOrGlueLen < 0) {
279
                returnList.add(new KnuthGlue(-penaltyOrGlueLen, 0, 0, new Position(null), true));
275
                returnList.add(new KnuthGlue(-penaltyOrGlueLen, 0, 0, new Position(null), true));
280
            }
276
            }
(-)src/java/org/apache/fop/layoutmgr/table/TableCaptionLayoutManager.java (-17 / +5 lines)
Lines 23-28 Link Here
23
import org.apache.fop.area.Block;
23
import org.apache.fop.area.Block;
24
import org.apache.fop.fo.flow.table.TableCaption;
24
import org.apache.fop.fo.flow.table.TableCaption;
25
import org.apache.fop.layoutmgr.BlockStackingLayoutManager;
25
import org.apache.fop.layoutmgr.BlockStackingLayoutManager;
26
import org.apache.fop.layoutmgr.Keep;
26
import org.apache.fop.layoutmgr.LayoutContext;
27
import org.apache.fop.layoutmgr.LayoutContext;
27
import org.apache.fop.layoutmgr.PositionIterator;
28
import org.apache.fop.layoutmgr.PositionIterator;
28
29
Lines 197-226 Link Here
197
    }
198
    }
198
199
199
    /** {@inheritDoc} */
200
    /** {@inheritDoc} */
200
    public int getKeepTogetherStrength() {
201
    public Keep getKeepWithNext() {
201
        int strength = KEEP_AUTO;
202
        return Keep.KEEP_AUTO;
202
        /* TODO Complete me!
203
        /* TODO Complete me!
203
        strength = Math.max(strength, KeepUtil.getKeepStrength(
204
                getTableCaptionFO().getKeepTogether().getWithinPage()));
205
        strength = Math.max(strength, KeepUtil.getKeepStrength(
206
                getTableCaptionFO().getKeepTogether().getWithinColumn()));
207
        */
208
        strength = Math.max(strength, getParentKeepTogetherStrength());
209
        return strength;
210
    }
211
212
    /** {@inheritDoc} */
213
    public int getKeepWithNextStrength() {
214
        return KEEP_AUTO;
215
        /* TODO Complete me!
216
        return KeepUtil.getCombinedBlockLevelKeepStrength(
204
        return KeepUtil.getCombinedBlockLevelKeepStrength(
217
                getTableCaptionFO().getKeepWithNext());
205
                getTableCaptionFO().getKeepWithNext());
218
        */
206
        */
219
    }
207
    }
220
208
221
    /** {@inheritDoc} */
209
    /** {@inheritDoc} */
222
    public int getKeepWithPreviousStrength() {
210
    public Keep getKeepWithPrevious() {
223
        return KEEP_AUTO;
211
        return Keep.KEEP_AUTO;
224
        /* TODO Complete me!
212
        /* TODO Complete me!
225
        return KeepUtil.getCombinedBlockLevelKeepStrength(
213
        return KeepUtil.getCombinedBlockLevelKeepStrength(
226
                getTableCaptionFO().getKeepWithPrevious());
214
                getTableCaptionFO().getKeepWithPrevious());
(-)src/java/org/apache/fop/layoutmgr/BlockStackingLayoutManager.java (-28 / +71 lines)
Lines 31-39 Link Here
31
import org.apache.fop.area.Block;
31
import org.apache.fop.area.Block;
32
import org.apache.fop.area.BlockParent;
32
import org.apache.fop.area.BlockParent;
33
import org.apache.fop.fo.FObj;
33
import org.apache.fop.fo.FObj;
34
import org.apache.fop.fo.Constants;
34
import org.apache.fop.fo.properties.BreakPropertySet;
35
import org.apache.fop.fo.properties.BreakPropertySet;
35
import org.apache.fop.fo.properties.CommonBorderPaddingBackground;
36
import org.apache.fop.fo.properties.CommonBorderPaddingBackground;
36
import org.apache.fop.fo.properties.SpaceProperty;
37
import org.apache.fop.fo.properties.SpaceProperty;
38
import org.apache.fop.fo.properties.KeepProperty;
37
import org.apache.fop.layoutmgr.inline.InlineLayoutManager;
39
import org.apache.fop.layoutmgr.inline.InlineLayoutManager;
38
import org.apache.fop.layoutmgr.inline.LineLayoutManager;
40
import org.apache.fop.layoutmgr.inline.LineLayoutManager;
39
import org.apache.fop.traits.MinOptMax;
41
import org.apache.fop.traits.MinOptMax;
Lines 259-265 Link Here
259
261
260
        updateContentAreaIPDwithOverconstrainedAdjust();
262
        updateContentAreaIPDwithOverconstrainedAdjust();
261
263
262
        List returnedList = null;
264
        List returnedList;
263
        List contentList = new LinkedList();
265
        List contentList = new LinkedList();
264
        List returnList = new LinkedList();
266
        List returnList = new LinkedList();
265
267
Lines 274-280 Link Here
274
276
275
        if (!firstVisibleMarkServed) {
277
        if (!firstVisibleMarkServed) {
276
            addKnuthElementsForSpaceBefore(returnList, alignment);
278
            addKnuthElementsForSpaceBefore(returnList, alignment);
277
            context.updateKeepWithPreviousPending(getKeepWithPreviousStrength());
279
            context.updateKeepWithPreviousPending(getKeepWithPrevious());
278
        }
280
        }
279
281
280
        addKnuthElementsForBorderPaddingBefore(returnList, !firstVisibleMarkServed);
282
        addKnuthElementsForBorderPaddingBefore(returnList, !firstVisibleMarkServed);
Lines 316-322 Link Here
316
            }
318
            }
317
            if (returnedList != null
319
            if (returnedList != null
318
                    && returnedList.size() == 1
320
                    && returnedList.size() == 1
319
                    && ((ListElement) returnedList.get(0)).isForcedBreak()) {
321
                    && ElementListUtils.startsWithForcedBreak(returnedList)) {
320
322
321
                if (curLM.isFinished() && !hasNextChildLM()) {
323
                if (curLM.isFinished() && !hasNextChildLM()) {
322
                    // a descendant of this block has break-before
324
                    // a descendant of this block has break-before
Lines 342-348 Link Here
342
344
343
                // "wrap" the Position inside each element
345
                // "wrap" the Position inside each element
344
                // moving the elements from contentList to returnList
346
                // moving the elements from contentList to returnList
345
                returnedList = new LinkedList();
346
                wrapPositionElements(contentList, returnList);
347
                wrapPositionElements(contentList, returnList);
347
348
348
                return returnList;
349
                return returnList;
Lines 375-381 Link Here
375
                    }
376
                    }
376
                    /* end of extension */
377
                    /* end of extension */
377
378
378
                    returnedList = new LinkedList();
379
                    wrapPositionElements(contentList, returnList);
379
                    wrapPositionElements(contentList, returnList);
380
380
381
                    return returnList;
381
                    return returnList;
Lines 394-400 Link Here
394
        }
394
        }
395
        /* end of extension */
395
        /* end of extension */
396
396
397
        returnedList = new LinkedList();
398
        if (!contentList.isEmpty()) {
397
        if (!contentList.isEmpty()) {
399
            wrapPositionElements(contentList, returnList);
398
            wrapPositionElements(contentList, returnList);
400
        } else if (forcedBreakAfterLast == null) {
399
        } else if (forcedBreakAfterLast == null) {
Lines 417-423 Link Here
417
            returnList.add(forcedBreakAfterLast);
416
            returnList.add(forcedBreakAfterLast);
418
        }
417
        }
419
418
420
        context.updateKeepWithNextPending(getKeepWithNextStrength());
419
        context.updateKeepWithNextPending(getKeepWithNext());
421
420
422
        setFinished(true);
421
        setFinished(true);
423
422
Lines 426-456 Link Here
426
425
427
    /**
426
    /**
428
     * Adds a break element to the content list between individual child elements.
427
     * Adds a break element to the content list between individual child elements.
429
     * @param contentList the content list to populate
428
     * @param contentList
430
     * @param context the current layout context
429
     * @param parentLC
431
     * @param childLC the currently active child layout context
430
     * @param childLC the currently active child layout context
432
     */
431
     */
433
    protected void addInBetweenBreak(List contentList, LayoutContext context,
432
    protected void addInBetweenBreak(List contentList, LayoutContext parentLC,
434
            LayoutContext childLC) {
433
                                     LayoutContext childLC) {
434
435
        if (mustKeepTogether()
435
        if (mustKeepTogether()
436
                || context.isKeepWithNextPending()
436
                || parentLC.isKeepWithNextPending()
437
                || childLC.isKeepWithPreviousPending()) {
437
                || childLC.isKeepWithPreviousPending()) {
438
438
439
            int strength = getKeepTogetherStrength();
439
            Keep keep = getKeepTogether();
440
440
441
            //Handle pending keep-with-next
441
            //Handle pending keep-with-next
442
            strength = Math.max(strength, context.getKeepWithNextPending());
442
            keep = keep.compare(parentLC.getKeepWithNextPending());
443
            context.clearKeepWithNextPending();
443
            parentLC.clearKeepWithNextPending();
444
444
445
            //Handle pending keep-with-previous from child LM
445
            //Handle pending keep-with-previous from child LM
446
            strength = Math.max(strength, childLC.getKeepWithPreviousPending());
446
            keep = keep.compare(childLC.getKeepWithPreviousPending());
447
            childLC.clearKeepWithPreviousPending();
447
            childLC.clearKeepWithPreviousPending();
448
448
449
            int penalty = KeepUtil.getPenaltyForKeep(strength);
450
451
            // add a penalty to forbid or discourage a break between blocks
449
            // add a penalty to forbid or discourage a break between blocks
452
            contentList.add(new BreakElement(
450
            contentList.add(new BreakElement(
453
                    new Position(this), penalty, context));
451
                    new Position(this), keep.getPenalty(),
452
                    keep.getContext(), parentLC));
454
            return;
453
            return;
455
        }
454
        }
456
455
Lines 481-487 Link Here
481
480
482
            // add a null penalty to allow a break between blocks
481
            // add a null penalty to allow a break between blocks
483
            contentList.add(new BreakElement(
482
            contentList.add(new BreakElement(
484
                    new Position(this), 0, context));
483
                    new Position(this), 0, Constants.EN_AUTO, parentLC));
485
        }
484
        }
486
    }
485
    }
487
486
Lines 817-852 Link Here
817
     * Retrieves and returns the keep-together strength from the parent element.
816
     * Retrieves and returns the keep-together strength from the parent element.
818
     * @return the keep-together strength
817
     * @return the keep-together strength
819
     */
818
     */
820
    protected int getParentKeepTogetherStrength() {
819
    protected Keep getParentKeepTogether() {
821
        int strength = KEEP_AUTO;
820
        Keep keep = Keep.KEEP_AUTO;
822
        if (getParent() instanceof BlockLevelLayoutManager) {
821
        if (getParent() instanceof BlockLevelLayoutManager) {
823
            strength = ((BlockLevelLayoutManager)getParent()).getKeepTogetherStrength();
822
            keep = ((BlockLevelLayoutManager)getParent()).getKeepTogether();
824
        } else if (getParent() instanceof InlineLayoutManager) {
823
        } else if (getParent() instanceof InlineLayoutManager) {
825
            if (((InlineLayoutManager) getParent()).mustKeepTogether()) {
824
            if (((InlineLayoutManager) getParent()).mustKeepTogether()) {
826
                strength = KEEP_ALWAYS;
825
                keep = Keep.KEEP_ALWAYS;
827
            }
826
            }
828
            //TODO Fix me
827
            //TODO Fix me
829
            //strength = ((InlineLayoutManager) getParent()).getKeepTogetherStrength();
828
            //strength = ((InlineLayoutManager) getParent()).getKeepTogetherStrength();
830
        }
829
        }
831
        return strength;
830
        return keep;
832
    }
831
    }
833
832
834
    /** {@inheritDoc} */
833
    /** {@inheritDoc} */
835
    public boolean mustKeepTogether() {
834
    public boolean mustKeepTogether() {
836
        return getKeepTogetherStrength() > KEEP_AUTO;
835
        return !getKeepTogether().isAuto();
837
    }
836
    }
838
837
839
    /** {@inheritDoc} */
838
    /** {@inheritDoc} */
840
    public boolean mustKeepWithPrevious() {
839
    public boolean mustKeepWithPrevious() {
841
        return getKeepWithPreviousStrength() > KEEP_AUTO;
840
        return !getKeepWithPrevious().isAuto();
842
    }
841
    }
843
842
844
    /** {@inheritDoc} */
843
    /** {@inheritDoc} */
845
    public boolean mustKeepWithNext() {
844
    public boolean mustKeepWithNext() {
846
        return getKeepWithNextStrength() > KEEP_AUTO;
845
        return !getKeepWithNext().isAuto();
847
    }
846
    }
848
847
848
    /** {@inheritDoc} */
849
    public Keep getKeepTogether() {
850
        Keep keep = Keep.getKeep(getKeepTogetherProperty());
851
        keep = keep.compare(getParentKeepTogether());
852
        return keep;
853
    }
854
855
    /** {@inheritDoc} */
856
    public Keep getKeepWithPrevious() {
857
        return Keep.getKeep(getKeepWithPreviousProperty());
858
    }
859
860
    /** {@inheritDoc} */
861
    public Keep getKeepWithNext() {
862
        return Keep.getKeep(getKeepWithNextProperty());
863
    }
864
849
    /**
865
    /**
866
     * {@inheritDoc}
867
     * Default implementation throws {@code IllegalStateException}
868
     * Must be implemented by the subclass, if applicable.
869
     */
870
    public KeepProperty getKeepTogetherProperty() {
871
        throw new IllegalStateException();
872
    }
873
874
    /**
875
     * {@inheritDoc}
876
     * Default implementation throws {@code IllegalStateException}
877
     * Must be implemented by the subclass, if applicable.
878
     */
879
    public KeepProperty getKeepWithPreviousProperty() {
880
        throw new IllegalStateException();
881
    }
882
883
    /**
884
     * {@inheritDoc}
885
     * Default implementation throws {@code IllegalStateException}
886
     * Must be implemented by the subclass, if applicable.
887
     */
888
    public KeepProperty getKeepWithNextProperty() {
889
        throw new IllegalStateException();
890
    }
891
892
    /**
850
     * Adds the unresolved elements for border and padding to a layout context so break
893
     * Adds the unresolved elements for border and padding to a layout context so break
851
     * possibilities can be properly constructed.
894
     * possibilities can be properly constructed.
852
     * @param context the layout context
895
     * @param context the layout context
(-)src/java/org/apache/fop/layoutmgr/BreakingAlgorithm.java (-5 / +16 lines)
Lines 611-616 Link Here
611
    }
611
    }
612
612
613
    /**
613
    /**
614
     * Return the last node that yielded a too short line.
615
     * @return  the node corresponding to the last too short line
616
     */
617
    protected final KnuthNode getLastTooShort() {
618
        return this.lastTooShort;
619
    }
620
621
    /**
614
     * Generic handler for a {@link KnuthElement} at the given {@code position},
622
     * Generic handler for a {@link KnuthElement} at the given {@code position},
615
     * taking into account whether the preceding element was a box, and which
623
     * taking into account whether the preceding element was a box, and which
616
     * type(s) of breaks are allowed.
624
     * type(s) of breaks are allowed.
Lines 647-653 Link Here
647
655
648
    /**
656
    /**
649
     * Handle a {@link KnuthBox}.
657
     * Handle a {@link KnuthBox}.
650
     * <em>Note: default implementation just adds the box's width
658
     * <br/><em>Note: default implementation just adds the box's width
651
     * to the total content width. Subclasses that do not keep track
659
     * to the total content width. Subclasses that do not keep track
652
     * of this themselves, but override this method, should remember
660
     * of this themselves, but override this method, should remember
653
     * to call {@code super.handleBox(box)} to avoid unwanted side-effects.</em>
661
     * to call {@code super.handleBox(box)} to avoid unwanted side-effects.</em>
Lines 808-821 Link Here
808
        lastDeactivated = null;
816
        lastDeactivated = null;
809
        lastTooLong = null;
817
        lastTooLong = null;
810
        for (int line = startLine; line < endLine; line++) {
818
        for (int line = startLine; line < endLine; line++) {
811
            if (!elementCanEndLine(element, line)) {
812
                continue;
813
            }
814
            for (KnuthNode node = getNode(line); node != null; node = node.next) {
819
            for (KnuthNode node = getNode(line); node != null; node = node.next) {
815
                if (node.position == elementIdx) {
820
                if (node.position == elementIdx) {
816
                    continue;
821
                    continue;
817
                }
822
                }
818
                int difference = computeDifference(node, element, elementIdx);
823
                int difference = computeDifference(node, element, elementIdx);
824
                if (!elementCanEndLine(element, node.line + 1, difference)) {
825
                    log.trace("Skipping legal break");
826
                    break;
827
                }
828
819
                double r = computeAdjustmentRatio(node, difference);
829
                double r = computeAdjustmentRatio(node, difference);
820
                int availableShrink = totalShrink - node.totalShrink;
830
                int availableShrink = totalShrink - node.totalShrink;
821
                int availableStretch = totalStretch - node.totalStretch;
831
                int availableStretch = totalStretch - node.totalStretch;
Lines 854-862 Link Here
854
     * number.
864
     * number.
855
     * @param element   the element
865
     * @param element   the element
856
     * @param line      the line number
866
     * @param line      the line number
867
     * @param difference
857
     * @return  {@code true} if the element can end the line
868
     * @return  {@code true} if the element can end the line
858
     */
869
     */
859
    protected boolean elementCanEndLine(KnuthElement element, int line) {
870
    protected boolean elementCanEndLine(KnuthElement element, int line, int difference) {
860
        return (!element.isPenalty()
871
        return (!element.isPenalty()
861
                || element.getP() < KnuthElement.INFINITE);
872
                || element.getP() < KnuthElement.INFINITE);
862
    }
873
    }
(-)src/java/org/apache/fop/fo/flow/table/EffRow.java (-21 / +15 lines)
Lines 23-30 Link Here
23
import java.util.List;
23
import java.util.List;
24
24
25
import org.apache.fop.fo.Constants;
25
import org.apache.fop.fo.Constants;
26
import org.apache.fop.layoutmgr.BlockLevelLayoutManager;
26
import org.apache.fop.layoutmgr.Keep;
27
import org.apache.fop.layoutmgr.KeepUtil;
28
import org.apache.fop.layoutmgr.table.TableRowIterator;
27
import org.apache.fop.layoutmgr.table.TableRowIterator;
29
import org.apache.fop.traits.MinOptMax;
28
import org.apache.fop.traits.MinOptMax;
30
import org.apache.fop.util.BreakUtil;
29
import org.apache.fop.util.BreakUtil;
Lines 170-189 Link Here
170
     *
169
     *
171
     * @return the strength of the keep-with-previous constraint
170
     * @return the strength of the keep-with-previous constraint
172
     */
171
     */
173
    public int getKeepWithPreviousStrength() {
172
    public Keep getKeepWithPrevious() {
174
        int strength = BlockLevelLayoutManager.KEEP_AUTO;
173
        Keep keep = Keep.KEEP_AUTO;
175
        TableRow row = getTableRow();
174
        TableRow row = getTableRow();
176
        if (row != null) {
175
        if (row != null) {
177
            strength = Math.max(strength,
176
            keep = Keep.getKeep(row.getKeepWithPrevious());
178
                    KeepUtil.getCombinedBlockLevelKeepStrength(row.getKeepWithPrevious()));
179
        }
177
        }
180
        for (Iterator iter = gridUnits.iterator(); iter.hasNext();) {
178
        for (Iterator iter = gridUnits.iterator(); iter.hasNext();) {
181
            GridUnit gu = (GridUnit) iter.next();
179
            GridUnit gu = (GridUnit) iter.next();
182
            if (gu.isPrimary()) {
180
            if (gu.isPrimary()) {
183
                strength = Math.max(strength, gu.getPrimary().getKeepWithPreviousStrength());
181
                keep = keep.compare(gu.getPrimary().getKeepWithPrevious());
184
            }
182
            }
185
        }
183
        }
186
        return strength;
184
        return keep;
187
    }
185
    }
188
186
189
    /**
187
    /**
Lines 192-211 Link Here
192
     *
190
     *
193
     * @return the strength of the keep-with-next constraint
191
     * @return the strength of the keep-with-next constraint
194
     */
192
     */
195
    public int getKeepWithNextStrength() {
193
    public Keep getKeepWithNext() {
196
        int strength = BlockLevelLayoutManager.KEEP_AUTO;
194
        Keep keep = Keep.KEEP_AUTO;
197
        TableRow row = getTableRow();
195
        TableRow row = getTableRow();
198
        if (row != null) {
196
        if (row != null) {
199
            strength = Math.max(strength,
197
            keep = Keep.getKeep(row.getKeepWithNext());
200
                    KeepUtil.getCombinedBlockLevelKeepStrength(row.getKeepWithNext()));
201
        }
198
        }
202
        for (Iterator iter = gridUnits.iterator(); iter.hasNext();) {
199
        for (Iterator iter = gridUnits.iterator(); iter.hasNext();) {
203
            GridUnit gu = (GridUnit) iter.next();
200
            GridUnit gu = (GridUnit) iter.next();
204
            if (!gu.isEmpty() && gu.getColSpanIndex() == 0 && gu.isLastGridUnitRowSpan()) {
201
            if (!gu.isEmpty() && gu.getColSpanIndex() == 0 && gu.isLastGridUnitRowSpan()) {
205
                strength = Math.max(strength, gu.getPrimary().getKeepWithNextStrength());
202
                keep = keep.compare(gu.getPrimary().getKeepWithNext());
206
            }
203
            }
207
        }
204
        }
208
        return strength;
205
        return keep;
209
    }
206
    }
210
207
211
    /**
208
    /**
Lines 213-228 Link Here
213
     * not take the parent table's keeps into account!
210
     * not take the parent table's keeps into account!
214
     * @return the keep-together strength
211
     * @return the keep-together strength
215
     */
212
     */
216
    public int getKeepTogetherStrength() {
213
    public Keep getKeepTogether() {
217
        TableRow row = getTableRow();
214
        TableRow row = getTableRow();
218
        int strength = BlockLevelLayoutManager.KEEP_AUTO;
215
        Keep keep = Keep.KEEP_AUTO;
219
        if (row != null) {
216
        if (row != null) {
220
            strength = Math.max(strength, KeepUtil.getKeepStrength(
217
            keep = Keep.getKeep(row.getKeepTogether());
221
                    row.getKeepTogether().getWithinPage()));
222
            strength = Math.max(strength, KeepUtil.getKeepStrength(
223
                    row.getKeepTogether().getWithinColumn()));
224
        }
218
        }
225
        return strength;
219
        return keep;
226
    }
220
    }
227
221
228
    /**
222
    /**
(-)src/java/org/apache/fop/fo/flow/table/PrimaryGridUnit.java (-12 / +11 lines)
Lines 19-32 Link Here
19
19
20
package org.apache.fop.fo.flow.table;
20
package org.apache.fop.fo.flow.table;
21
21
22
import java.util.LinkedList;
23
import java.util.List;
22
import java.util.List;
24
23
25
import org.apache.fop.fo.Constants;
24
import org.apache.fop.fo.Constants;
26
import org.apache.fop.fo.FONode;
25
import org.apache.fop.fo.FONode;
27
import org.apache.fop.fo.properties.CommonBorderPaddingBackground;
26
import org.apache.fop.fo.properties.CommonBorderPaddingBackground;
28
import org.apache.fop.layoutmgr.BlockLevelLayoutManager;
29
import org.apache.fop.layoutmgr.ElementListUtils;
27
import org.apache.fop.layoutmgr.ElementListUtils;
28
import org.apache.fop.layoutmgr.Keep;
30
import org.apache.fop.layoutmgr.table.TableCellLayoutManager;
29
import org.apache.fop.layoutmgr.table.TableCellLayoutManager;
31
30
32
/**
31
/**
Lines 54-61 Link Here
54
    private boolean isSeparateBorderModel;
53
    private boolean isSeparateBorderModel;
55
    private int halfBorderSeparationBPD;
54
    private int halfBorderSeparationBPD;
56
55
57
    private int keepWithPrevious = BlockLevelLayoutManager.KEEP_AUTO;
56
    private Keep keepWithPrevious = Keep.KEEP_AUTO;
58
    private int keepWithNext = BlockLevelLayoutManager.KEEP_AUTO;
57
    private Keep keepWithNext = Keep.KEEP_AUTO;
59
    private int breakBefore = Constants.EN_AUTO;
58
    private int breakBefore = Constants.EN_AUTO;
60
    private int breakAfter = Constants.EN_AUTO;
59
    private int breakAfter = Constants.EN_AUTO;
61
60
Lines 334-349 Link Here
334
     *
333
     *
335
     * @return the keep-with-previous strength
334
     * @return the keep-with-previous strength
336
     */
335
     */
337
    public int getKeepWithPreviousStrength() {
336
    public Keep getKeepWithPrevious() {
338
        return keepWithPrevious;
337
        return keepWithPrevious;
339
    }
338
    }
340
339
341
    /**
340
    /**
342
     * Don't use, reserved for TableCellLM. TODO
341
     * Don't use, reserved for TableCellLM. TODO
343
     * @param strength the keep strength
342
     * @param keep the keep strength
344
     */
343
     */
345
    public void setKeepWithPreviousStrength(int strength) {
344
    public void setKeepWithPrevious(Keep keep) {
346
        this.keepWithPrevious = strength;
345
        this.keepWithPrevious = keep;
347
    }
346
    }
348
347
349
    /**
348
    /**
Lines 352-367 Link Here
352
     *
351
     *
353
     * @return the keep-with-next strength
352
     * @return the keep-with-next strength
354
     */
353
     */
355
    public int getKeepWithNextStrength() {
354
    public Keep getKeepWithNext() {
356
        return keepWithNext;
355
        return keepWithNext;
357
    }
356
    }
358
357
359
    /**
358
    /**
360
     * Don't use, reserved for TableCellLM. TODO
359
     * Don't use, reserved for TableCellLM. TODO
361
     * @param strength the keep strength
360
     * @param keep the keep strength
362
     */
361
     */
363
    public void setKeepWithNextStrength(int strength) {
362
    public void setKeepWithNext(Keep keep) {
364
        this.keepWithNext = strength;
363
        this.keepWithNext = keep;
365
    }
364
    }
366
365
367
    /**
366
    /**
(-)test/layoutengine/standard-testcases/inline_block_nested_6.xml (-4 / +3 lines)
Lines 52-67 Link Here
52
      <skip>5</skip>
52
      <skip>5</skip>
53
      <!-- penalty between blocks b11 and b12, set by InlineLM in b1 -->
53
      <!-- penalty between blocks b11 and b12, set by InlineLM in b1 -->
54
      <penalty w="0" p="0"/>
54
      <penalty w="0" p="0"/>
55
      <skip>6</skip>
55
      <skip>5</skip>
56
      <!-- penalty between blocks b21 and b22, set by InlineLM in b2 -->
56
      <!-- penalty between blocks b21 and b22, set by InlineLM in b2 -->
57
      <!-- keep-together.within-page="always" -->
57
      <!-- keep-together.within-page="always" -->
58
      <penalty w="0" p="1000"/>
58
      <penalty w="0" p="1000"/>
59
      <skip>6</skip>
59
      <skip>3</skip>
60
      <!-- penalty between blocks b31 and b32, set by InlineLM in b3 -->
60
      <!-- penalty between blocks b31 and b32, set by InlineLM in b3 -->
61
      <!-- keep-with-next.within-page="always" -->
61
      <!-- keep-with-next.within-page="always" -->
62
      <penalty w="0" p="1000"/>
62
      <penalty w="0" p="1000"/>
63
      <skip>5</skip>
63
      <skip>14</skip>
64
      <skip>3</skip>
65
    </element-list>
64
    </element-list>
66
  </checks>
65
  </checks>
67
</testcase>			          
66
</testcase>			          
(-)test/layoutengine/standard-testcases/keep_within-column_basic.xml (+155 lines)
Line 0 Link Here
1
<?xml version="1.0" encoding="UTF-8"?>
2
<!--
3
  Licensed to the Apache Software Foundation (ASF) under one or more
4
  contributor license agreements.  See the NOTICE file distributed with
5
  this work for additional information regarding copyright ownership.
6
  The ASF licenses this file to You under the Apache License, Version 2.0
7
  (the "License"); you may not use this file except in compliance with
8
  the License.  You may obtain a copy of the License at
9
10
       http://www.apache.org/licenses/LICENSE-2.0
11
12
  Unless required by applicable law or agreed to in writing, software
13
  distributed under the License is distributed on an "AS IS" BASIS,
14
  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
15
  See the License for the specific language governing permissions and
16
  limitations under the License.
17
-->
18
<!-- $Id$ -->
19
<testcase>
20
  <info>
21
    <p>
22
      This test checks whether keeps within-column are respected.
23
    </p>
24
  </info>
25
  <fo>
26
    <fo:root xmlns:fo="http://www.w3.org/1999/XSL/Format">
27
      <fo:layout-master-set>
28
        <fo:simple-page-master master-name="page" page-width="400pt" page-height="70pt">
29
          <fo:region-body column-count="5" />
30
        </fo:simple-page-master>
31
      </fo:layout-master-set>
32
      <fo:page-sequence master-reference="page" font-size="10pt">
33
        <fo:flow flow-name="xsl-region-body">
34
          <fo:block break-before="page">
35
            <!-- simple test: keep the second block together within
36
                 one column, breaking the preceding block early 
37
                 if necessary -->
38
            <fo:block id="block-1">
39
              [BOB-1] foo bar foo bar foo bar foo bar foo bar
40
              foo bar foo bar foo bar foo bar foo bar foo bar
41
              foo bar foo bar foo bar foo bar foo bar foo bar
42
              foo bar foo bar foo bar foo bar foo bar [EOB-1]
43
            </fo:block>
44
            <fo:block id="block-2" keep-together.within-column="always">
45
              [BOB-2] foo bar foo bar foo bar foo bar foo [EOB-2]
46
            </fo:block>
47
          </fo:block>
48
          <fo:block break-before="page">
49
            <!-- same as the first, but now a nested block
50
                 with a higher integer value, and some content
51
                 following -->
52
            <fo:block id="block-3" keep-together.within-column="5">
53
              [BOB-3] foo bar foo bar foo bar foo bar foo bar
54
              foo bar foo bar foo bar foo bar foo bar foo bar
55
              foo bar foo bar foo bar foo bar foo bar foo bar
56
              foo bar foo bar foo bar foo bar foo bar foo bar
57
              foo bar foo bar foo bar foo bar foo bar foo bar
58
              <fo:block font-weight="bold" id="block-3a" keep-together.within-column="always">
59
                [BOB-3a] foo bar foo bar foo bar foo bar foo [EOB-3a]
60
              </fo:block>
61
              foo bar foo bar foo bar foo bar foo bar foo bar
62
              foo bar foo bar foo bar foo bar foo bar foo bar
63
              foo bar foo bar foo bar foo bar foo bar [EOB-3]
64
            </fo:block>
65
          </fo:block>
66
          <fo:block break-before="page">
67
            <!-- nested block must be kept together within the same
68
                 page, while the outer block may be broken, if necessary -->
69
            <fo:block font-style="italic" id="block-4" keep-together.within-column="5">
70
              [BOB-4] foo bar foo bar foo bar foo bar foo bar
71
              foo bar foo bar foo bar foo bar foo bar foo bar
72
              foo bar foo bar foo bar foo bar foo bar foo bar
73
              foo bar foo bar foo bar foo bar foo bar foo bar
74
              foo bar foo bar foo bar foo bar foo bar foo bar
75
              foo bar foo bar foo bar foo bar foo bar foo bar
76
              <fo:block id="block-4a" keep-together.within-page="always">
77
                [BOB-4a] foo bar foo bar foo bar foo bar foo bar
78
                foo bar foo bar foo bar foo bar foo bar foo bar
79
                foo bar foo bar foo bar foo bar foo bar foo bar
80
                foo bar foo bar foo bar foo bar foo bar foo bar
81
                foo bar foo bar foo bar foo bar foo bar foo bar
82
                foo bar foo bar foo bar foo bar foo bar foo bar
83
                foo bar foo bar foo bar foo bar foo bar foo bar
84
                foo bar foo bar foo bar foo bar foo bar [EOB-4a]
85
              </fo:block>
86
              foo bar foo bar foo bar foo bar foo bar foo bar
87
              foo bar foo bar foo bar foo bar foo bar foo bar
88
              foo bar foo bar foo bar foo bar foo bar [EOB-4]
89
            </fo:block>
90
          </fo:block>
91
          <fo:block break-before="page">
92
            <!-- test keep-with-next in conjunction with keep-together
93
                 respecting the default value for widows/orphans -->
94
            <fo:block id="block-5">
95
              <fo:block id="block-5a">
96
              [BOB-5a] foo bar foo bar foo bar foo bar foo bar
97
              foo bar foo bar foo bar foo bar foo bar foo bar
98
              foo bar foo bar foo bar foo bar foo bar foo bar
99
              foo bar foo bar foo bar foo bar foo bar foo bar
100
              foo bar foo bar foo bar foo bar foo bar foo bar
101
              foo bar foo bar foo bar foo bar foo bar [EOB-5a]
102
              </fo:block>
103
              <fo:block id="block-5b" keep-with-next.within-column="always">
104
              [BOB-5b] foo bar foo bar foo bar foo bar foo bar
105
              foo bar foo bar foo bar foo bar foo bar [EOB-5b]
106
              </fo:block>
107
              <fo:block id="block-5c" keep-together.within-column="always">
108
              [BOB-5c] foo bar foo bar foo bar foo bar foo bar
109
              foo bar foo bar foo bar foo bar foo bar [EOB-5c]
110
              </fo:block>
111
            </fo:block>
112
          </fo:block>
113
          <fo:block break-before="page">
114
            <!-- test keep-together in conjunction with keep-with-previous -->
115
            <fo:block id="block-6">
116
              <fo:block id="block-6a">
117
              [BOB-6a] foo bar foo bar foo bar foo bar foo bar
118
              foo bar foo bar foo bar foo bar foo bar foo bar
119
              foo bar foo bar foo bar foo bar foo bar foo bar
120
              foo bar foo bar foo bar foo bar foo bar foo bar
121
              foo bar foo bar foo bar foo bar foo bar [EOB-6a]
122
              </fo:block>
123
              <fo:block id="block-6b" keep-together.within-column="always">
124
              [BOB-6b] foo bar foo bar foo bar foo bar foo bar [EOB-6b]
125
              </fo:block>
126
              <fo:block id="block-6c" keep-with-previous.within-column="always">
127
              [BOB-6c] foo bar foo bar foo bar foo bar foo bar
128
              foo bar foo bar foo bar foo bar foo bar [EOB-6c]
129
              </fo:block>
130
            </fo:block>
131
          </fo:block>
132
        </fo:flow>
133
      </fo:page-sequence>
134
    </fo:root>
135
  </fo>
136
  <checks>
137
    <!-- check total page-count -->
138
    <eval expected="10" xpath="count(//page)" />
139
    <!-- block-2 should end up in its own column, column 4 -->
140
    <eval expected="1" xpath="count(//block[@prod-id='block-2']/ancestor::flow)" />
141
    <eval expected="3" xpath="count(//block[@prod-id='block-2']/ancestor::flow/preceding-sibling::flow)" />
142
    <!-- block-3a should end up in its own column, column 5 -->
143
    <eval expected="1" xpath="count(//block[@prod-id='block-3a']/ancestor::flow)" />
144
    <eval expected="4" xpath="count(//block[@prod-id='block-3a']/ancestor::flow/preceding-sibling::flow)" />
145
    <!-- block-4a should end up in its own page -->
146
    <eval expected="1" xpath="count(//block[@prod-id='block-4a']/ancestor::page)" />
147
    <!-- block 5c should end up in its own column, with two preceding lines from block 5b -->
148
    <eval expected="1" xpath="count(//block[@prod-id='block-5c']/ancestor::flow)" />
149
    <eval expected="2" xpath="count(//block[@prod-id='block-5c']/preceding-sibling::block/lineArea)" />
150
    <!-- block 6b should end up in its own column, with two following lines from block 6c -->
151
    <eval expected="1" xpath="count(//block[@prod-id='block-6b']/ancestor::flow)" />
152
    <eval expected="2" xpath="count(//block[@prod-id='block-6b']/following-sibling::block/lineArea)" />
153
  </checks>
154
</testcase>
155
(-)test/layoutengine/standard-testcases/table-row_keep-together.xml (-3 / +3 lines)
Lines 64-73 Link Here
64
    <element-list category="breaker" index="0">
64
    <element-list category="breaker" index="0">
65
      <box w="14400"/>
65
      <box w="14400"/>
66
      <penalty w="0" p="0"/>
66
      <penalty w="0" p="0"/>
67
      <box w="28800"/>
68
      <penalty w="0" p="0"/>
69
      <box w="14400"/>
67
      <box w="14400"/>
70
      <skip>3</skip>
68
      <penalty w="0" p="INF"/>
69
      <box w="14400"/>
70
      <skip>5</skip>
71
    </element-list>
71
    </element-list>
72
  </checks>
72
  </checks>
73
</testcase>
73
</testcase>
(-)test/layoutengine/standard-testcases/table_keep-together.xml (-1 / +3 lines)
Lines 101-109 Link Here
101
    <element-list category="breaker" index="0">
101
    <element-list category="breaker" index="0">
102
      <box w="14400"/>
102
      <box w="14400"/>
103
      <penalty w="0" p="0"/>
103
      <penalty w="0" p="0"/>
104
      <box w="28800"/>
104
      <box w="14400"/>
105
      <penalty w="0" p="INF"/>
105
      <penalty w="0" p="INF"/>
106
      <box w="14400"/>
106
      <box w="14400"/>
107
      <penalty w="0" p="INF"/>
108
      <box w="14400"/>
107
      <penalty w="0" p="0"/>
109
      <penalty w="0" p="0"/>
108
      <box w="14400"/>
110
      <box w="14400"/>
109
      <skip>3</skip>
111
      <skip>3</skip>

Return to bug 46905