]> source.dussan.org Git - xmlgraphics-fop.git/commitdiff
Test case for showing a problem with the Knuth algorithm.
authorJeremias Maerki <jeremias@apache.org>
Wed, 5 Oct 2005 18:04:59 +0000 (18:04 +0000)
committerJeremias Maerki <jeremias@apache.org>
Wed, 5 Oct 2005 18:04:59 +0000 (18:04 +0000)
git-svn-id: https://svn.apache.org/repos/asf/xmlgraphics/fop/trunk@295059 13f79535-47bb-0310-9956-ffa450edef68

test/java/org/apache/fop/KnuthAlgorithmTestCase.java [new file with mode: 0644]

diff --git a/test/java/org/apache/fop/KnuthAlgorithmTestCase.java b/test/java/org/apache/fop/KnuthAlgorithmTestCase.java
new file mode 100644 (file)
index 0000000..4a7047a
--- /dev/null
@@ -0,0 +1,142 @@
+/*
+ * Copyright 2005 The Apache Software Foundation.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+/* $Id$ */
+
+package org.apache.fop;
+
+import java.util.List;
+
+import org.apache.fop.layoutmgr.BreakingAlgorithm;
+import org.apache.fop.layoutmgr.ElementListObserver;
+import org.apache.fop.layoutmgr.KnuthBox;
+import org.apache.fop.layoutmgr.KnuthGlue;
+import org.apache.fop.layoutmgr.KnuthPenalty;
+import org.apache.fop.layoutmgr.KnuthSequence;
+
+import junit.framework.TestCase;
+
+/**
+ * Tests the Knuth algorithm implementation.
+ */
+public class KnuthAlgorithmTestCase extends TestCase {
+
+    /** @see junit.framework.TestCase#setUp() */
+    protected void setUp() throws Exception {
+        super.setUp();
+        DebugHelper.registerStandardElementListObservers();
+    }
+
+    private KnuthSequence getKnuthSequence1() {
+        KnuthSequence seq = new KnuthSequence();
+        for (int i = 0; i < 5; i++) {
+            seq.add(new KnuthBox(0, null, true));
+            seq.add(new KnuthPenalty(0, KnuthPenalty.INFINITE, false, null, true));
+            seq.add(new KnuthGlue(5000, 0, 0, null, true));
+            seq.add(new KnuthBox(10000, null, false));
+            if (i < 4) {
+                seq.add(new KnuthPenalty(0, 0, false, null, false));
+                seq.add(new KnuthGlue(-5000, 0, 0, null, true));
+            }
+        }
+        
+        seq.add(new KnuthPenalty(0, KnuthPenalty.INFINITE, false, null, false));
+        seq.add(new KnuthGlue(0, Integer.MAX_VALUE, 0, null, false));
+        seq.add(new KnuthPenalty(0, -KnuthPenalty.INFINITE, false, null, false));
+        ElementListObserver.observe(seq, "test", null);
+        return seq;
+    }
+    
+    /**
+     * Tests a special condition where a negative-length glue occurs directly after a break
+     * possibility.
+     * @throws Exception if an error occurs
+     */
+    public void test1() throws Exception {
+        MyBreakingAlgorithm algo = new MyBreakingAlgorithm(0, 0, true, true);
+        algo.setConstantLineWidth(30000);
+        KnuthSequence seq = getKnuthSequence1();
+        algo.findBreakingPoints(seq, 1, true, BreakingAlgorithm.ALL_BREAKS);
+        Part[] parts = algo.getParts();
+        assertEquals("Sequence must produce 3 parts", 3, parts.length);
+        assertEquals(5000, parts[0].difference);
+        assertEquals(5000, parts[1].difference);
+    }
+    
+    private class Part {
+        private int difference;
+        private double ratio;
+        private int position;
+    }
+    
+    private class MyBreakingAlgorithm extends BreakingAlgorithm {
+
+        private List parts = new java.util.ArrayList();
+        
+        public MyBreakingAlgorithm(int align, int alignLast, boolean first, 
+                    boolean partOverflowRecovery) {
+            super(align, alignLast, first, partOverflowRecovery);
+        }
+
+        public Part[] getParts() {
+            return (Part[])parts.toArray(new Part[parts.size()]);
+        }
+        
+        public void updateData1(int total, double demerits) {
+            //nop
+        }
+
+        public void updateData2(KnuthNode bestActiveNode, KnuthSequence sequence, int total) {
+            int difference = bestActiveNode.difference;
+            // it is always allowed to adjust space, so the ratio must be set regardless of
+            // the value of the property display-align; the ratio must be <= 1
+            double ratio = bestActiveNode.adjustRatio;
+            if (ratio < 0) {
+                // page break with a negative difference:
+                // spaces always have enough shrink
+                difference = 0;
+            } else if (ratio <= 1 && bestActiveNode.line < total) {
+                // not-last page break with a positive difference smaller than the available 
+                // stretch: spaces can stretch to fill the whole difference
+                difference = 0;
+            } else if (ratio > 1) {
+                // not-last page with a positive difference greater than the available stretch
+                // spaces can stretch to fill the difference only partially
+                ratio = 1;
+                difference -= bestActiveNode.availableStretch;
+            } else {
+                // last page with a positive difference:
+                // spaces do not need to stretch
+                ratio = 0;
+            }
+
+            // add nodes at the beginning of the list, as they are found
+            // backwards, from the last one to the first one
+            Part part = new Part();
+            part.difference = difference;
+            part.ratio = ratio;
+            part.position = bestActiveNode.position;
+            parts.add(0, part);
+        }
+
+        protected int filterActiveNodes() {
+            //nop
+            return 0;
+        }
+        
+    }
+    
+}