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: Keep.java 985537 2010-08-14 17:17:00Z jeremias $ */ 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 * Object representing a keep constraint, corresponding 28 * to the XSL-FO <a href="http://www.w3.org/TR/xsl/#d0e26492">keep properties</a>. 29 */ 30 public final class Keep { 31 32 /** The integer value for "auto" keep strength. */ 33 private static final int STRENGTH_AUTO = Integer.MIN_VALUE; 34 35 /** The integer value for "always" keep strength. */ 36 private static final int STRENGTH_ALWAYS = Integer.MAX_VALUE; 37 38 /** keep auto */ 39 public static final Keep KEEP_AUTO = new Keep(STRENGTH_AUTO, Constants.EN_AUTO); 40 41 /** keep always */ 42 public static final Keep KEEP_ALWAYS = new Keep(STRENGTH_ALWAYS, Constants.EN_LINE); 43 44 private int strength; 45 46 private int context; 47 Keep(int strength, int context)48 private Keep(int strength, int context) { 49 this.strength = strength; 50 this.context = context; 51 } 52 getKeepStrength(Property keep)53 private static int getKeepStrength(Property keep) { 54 if (keep.isAuto()) { 55 return STRENGTH_AUTO; 56 } else if (keep.getEnum() == Constants.EN_ALWAYS) { 57 return STRENGTH_ALWAYS; 58 } else { 59 return keep.getNumber().intValue(); 60 } 61 } 62 63 /** 64 * Obtain a Keep instance corresponding to the given {@link KeepProperty} 65 * 66 * @param keepProperty the {@link KeepProperty} 67 * @return a new instance corresponding to the given property 68 */ getKeep(KeepProperty keepProperty)69 public static Keep getKeep(KeepProperty keepProperty) { 70 Keep keep = new Keep(STRENGTH_AUTO, Constants.EN_AUTO); 71 keep.update(keepProperty.getWithinPage(), Constants.EN_PAGE); 72 keep.update(keepProperty.getWithinColumn(), Constants.EN_COLUMN); 73 keep.update(keepProperty.getWithinLine(), Constants.EN_LINE); 74 return keep; 75 } 76 update(Property keep, int context)77 private void update(Property keep, int context) { 78 if (!keep.isAuto()) { 79 this.strength = getKeepStrength(keep); 80 this.context = context; 81 } 82 } 83 84 /** @return {@code true} if the keep property was specified as "auto" */ isAuto()85 public boolean isAuto() { 86 return strength == STRENGTH_AUTO; 87 } 88 89 /** 90 * Returns the context of this keep. 91 * 92 * @return one of {@link Constants#EN_LINE}, {@link Constants#EN_COLUMN} or 93 * {@link Constants#EN_PAGE} 94 */ getContext()95 public int getContext() { 96 return context; 97 } 98 99 /** @return the penalty value corresponding to the strength of this Keep */ getPenalty()100 public int getPenalty() { 101 if (strength == STRENGTH_AUTO) { 102 return 0; 103 } else if (strength == STRENGTH_ALWAYS) { 104 return KnuthElement.INFINITE; 105 } else { 106 return KnuthElement.INFINITE - 1; 107 } 108 } 109 getKeepContextPriority(int context)110 private static int getKeepContextPriority(int context) { 111 switch (context) { 112 case Constants.EN_LINE: return 0; 113 case Constants.EN_COLUMN: return 1; 114 case Constants.EN_PAGE: return 2; 115 case Constants.EN_AUTO: return 3; 116 default: throw new IllegalArgumentException(); 117 } 118 } 119 120 /** 121 * Compare this Keep instance to another one, and return the 122 * stronger one if the context is the same 123 * 124 * @param other the instance to compare to 125 * @return the winning Keep instance 126 */ compare(Keep other)127 public Keep compare(Keep other) { 128 129 /* check strength "always" first, regardless of priority */ 130 if (this.strength == STRENGTH_ALWAYS 131 && this.strength > other.strength) { 132 return this; 133 } else if (other.strength == STRENGTH_ALWAYS 134 && other.strength > this.strength) { 135 return other; 136 } 137 138 int pThis = getKeepContextPriority(this.context); 139 int pOther = getKeepContextPriority(other.context); 140 141 /* equal priority: strongest wins */ 142 if (pThis == pOther) { 143 return (strength >= other.strength) ? this : other; 144 } 145 146 /* different priority: lowest priority wins */ 147 return (pThis < pOther) ? this : other; 148 } 149 150 /** {@inheritDoc} */ toString()151 public String toString() { 152 return (strength == STRENGTH_AUTO) ? "auto" 153 : (strength == STRENGTH_ALWAYS) ? "always" 154 : Integer.toString(strength); 155 } 156 } 157