123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346 |
- /*
- * Licensed to the Apache Software Foundation (ASF) under one or more
- * contributor license agreements. See the NOTICE file distributed with
- * this work for additional information regarding copyright ownership.
- * The ASF licenses this file to You under the Apache License, Version 2.0
- * (the "License"); you may not use this file except in compliance with
- * the License. You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
- /* $Id$ */
-
- package org.apache.fop.traits;
-
- import java.io.Serializable;
-
- /**
- * This class holds the resolved (as mpoints) form of a
- * {@link org.apache.fop.fo.properties.LengthRangeProperty} or
- * {@link org.apache.fop.fo.properties.SpaceProperty} type property value.
- * <p/>
- * Instances of this class are immutable. All arithmetic methods like {@link #plus(MinOptMax) plus},
- * {@link #minus(MinOptMax) minus} or {@link #mult(int) mult} return a different instance. So it is
- * possible to pass around instances without copying.
- * <p/>
- * <code>MinOptMax</code> values are used during layout calculations.
- */
- public final class MinOptMax implements Serializable {
-
- private static final long serialVersionUID = -4791524475122206142L;
-
- /**
- * The zero <code>MinOptMax</code> instance with <code>min == opt == max == 0</code>.
- */
- public static final MinOptMax ZERO = getInstance(0);
-
- private final int min;
- private final int opt;
- private final int max;
-
- /**
- * Returns an instance of <code>MinOptMax</code> with the given values.
- *
- * @param min the minimum value
- * @param opt the optimum value
- * @param max the maximum value
- * @return the corresponding instance
- * @throws IllegalArgumentException if <code>min > opt || max < opt</code>.
- */
- public static MinOptMax getInstance(int min, int opt, int max) throws IllegalArgumentException {
- if (min > opt) {
- throw new IllegalArgumentException("min (" + min + ") > opt (" + opt + ")");
- }
- if (max < opt) {
- throw new IllegalArgumentException("max (" + max + ") < opt (" + opt + ")");
- }
- return new MinOptMax(min, opt, max);
- }
-
- /**
- * Returns an instance of <code>MinOptMax</code> with one fixed value for all three
- * properties (min, opt, max).
- *
- * @param value the value for min, opt and max
- * @return the corresponding instance
- * @see #isStiff()
- */
- public static MinOptMax getInstance(int value) {
- return new MinOptMax(value, value, value);
- }
-
- // Private constructor without consistency checks
- private MinOptMax(int min, int opt, int max) {
- assert min <= opt && opt <= max;
- this.min = min;
- this.opt = opt;
- this.max = max;
- }
-
- /**
- * Returns the minimum value of this <code>MinOptMax</code>.
- *
- * @return the minimum value of this <code>MinOptMax</code>.
- */
- public int getMin() {
- return min;
- }
-
- /**
- * Returns the optimum value of this <code>MinOptMax</code>.
- *
- * @return the optimum value of this <code>MinOptMax</code>.
- */
- public int getOpt() {
- return opt;
- }
-
- /**
- * Returns the maximum value of this <code>MinOptMax</code>.
- *
- * @return the maximum value of this <code>MinOptMax</code>.
- */
- public int getMax() {
- return max;
- }
-
- /**
- * Returns the shrinkability of this <code>MinOptMax</code> which is the absolute difference
- * between <code>min</code> and <code>opt</code>.
- *
- * @return the shrinkability of this <code>MinOptMax</code> which is always non-negative.
- */
- public int getShrink() {
- return opt - min;
- }
-
- /**
- * Returns the stretchability of this <code>MinOptMax</code> which is the absolute difference
- * between <code>opt</code> and <code>max</code>.
- *
- * @return the stretchability of this <code>MinOptMax</code> which is always non-negative.
- */
- public int getStretch() {
- return max - opt;
- }
-
- /**
- * Returns the sum of this <code>MinOptMax</code> and the given <code>MinOptMax</code>.
- *
- * @param operand the second operand of the sum (the first is this instance itself),
- * @return the sum of this <code>MinOptMax</code> and the given <code>MinOptMax</code>.
- */
- public MinOptMax plus(MinOptMax operand) {
- return new MinOptMax(min + operand.min, opt + operand.opt, max + operand.max);
- }
-
-
- /**
- * Adds the given value to all three components of this instance and returns the result.
- *
- * @param value value to add to the min, opt, max components
- * @return the result of the addition
- */
- public MinOptMax plus(int value) {
- return new MinOptMax(min + value, opt + value, max + value);
- }
-
- /**
- * Returns the difference of this <code>MinOptMax</code> and the given
- * <code>MinOptMax</code>. This instance must be a compound of the operand and another
- * <code>MinOptMax</code>, that is, there must exist a <code>MinOptMax</code> <i>m</i>
- * such that <code>this.equals(m.plus(operand))</code>. In other words, the operand
- * must have less shrink and stretch than this instance.
- *
- * @param operand the value to be subtracted
- * @return the difference of this <code>MinOptMax</code> and the given
- * <code>MinOptMax</code>.
- * @throws ArithmeticException if this instance has strictly less shrink or stretch
- * than the operand
- */
- public MinOptMax minus(MinOptMax operand) throws ArithmeticException {
- checkCompatibility(getShrink(), operand.getShrink(), "shrink");
- checkCompatibility(getStretch(), operand.getStretch(), "stretch");
- return new MinOptMax(min - operand.min, opt - operand.opt, max - operand.max);
- }
-
- private void checkCompatibility(int thisElasticity, int operandElasticity, String msge) {
- if (thisElasticity < operandElasticity) {
- throw new ArithmeticException(
- "Cannot subtract a MinOptMax from another MinOptMax that has less " + msge
- + " (" + thisElasticity + " < " + operandElasticity + ")");
- }
- }
-
- /**
- * Subtracts the given value from all three components of this instance and returns the result.
- *
- * @param value value to subtract from the min, opt, max components
- * @return the result of the subtraction
- */
- public MinOptMax minus(int value) {
- return new MinOptMax(min - value, opt - value, max - value);
- }
-
- /**
- * Do not use, backwards compatibility only. Returns an instance with the
- * given value added to the minimal value.
- *
- * @param minOperand the minimal value to be added.
- * @return an instance with the given value added to the minimal value.
- * @throws IllegalArgumentException if
- * <code>min + minOperand > opt || max < opt</code>.
- */
- public MinOptMax plusMin(int minOperand) throws IllegalArgumentException {
- return getInstance(min + minOperand, opt, max);
- }
-
- /**
- * Do not use, backwards compatibility only. Returns an instance with the
- * given value subtracted to the minimal value.
- *
- * @param minOperand the minimal value to be subtracted.
- * @return an instance with the given value subtracted to the minimal value.
- * @throws IllegalArgumentException if
- * <code>min - minOperand > opt || max < opt</code>.
- */
- public MinOptMax minusMin(int minOperand) throws IllegalArgumentException {
- return getInstance(min - minOperand, opt, max);
- }
-
- /**
- * Do not use, backwards compatibility only. Returns an instance with the
- * given value added to the maximal value.
- *
- * @param maxOperand the maximal value to be added.
- * @return an instance with the given value added to the maximal value.
- * @throws IllegalArgumentException if
- * <code>min > opt || max < opt + maxOperand</code>.
- */
- public MinOptMax plusMax(int maxOperand) throws IllegalArgumentException {
- return getInstance(min, opt, max + maxOperand);
- }
-
- /**
- * Do not use, backwards compatibility only. Returns an instance with the
- * given value subtracted to the maximal value.
- *
- * @param maxOperand the maximal value to be subtracted.
- * @return an instance with the given value subtracted to the maximal value.
- * @throws IllegalArgumentException if
- * <code>min > opt || max < opt - maxOperand</code>.
- */
- public MinOptMax minusMax(int maxOperand) throws IllegalArgumentException {
- return getInstance(min, opt, max - maxOperand);
- }
-
- /**
- * Returns the product of this <code>MinOptMax</code> and the given factor.
- *
- * @param factor the factor
- * @return the product of this <code>MinOptMax</code> and the given factor
- * @throws IllegalArgumentException if the factor is negative
- */
- public MinOptMax mult(int factor) throws IllegalArgumentException {
- if (factor < 0) {
- throw new IllegalArgumentException("factor < 0; was: " + factor);
- } else if (factor == 1) {
- return this;
- } else {
- return getInstance(min * factor, opt * factor, max * factor);
- }
- }
-
- /**
- * Determines whether this <code>MinOptMax</code> represents a non-zero dimension, which means
- * that not all values (min, opt, max) are zero.
- *
- * @return <code>true</code> if this <code>MinOptMax</code> represents a non-zero dimension;
- * <code>false</code> otherwise.
- */
- public boolean isNonZero() {
- return min != 0 || max != 0;
- }
-
- /**
- * Determines whether this <code>MinOptMax</code> doesn't allow for shrinking or stretching,
- * which means that all values (min, opt, max) are the same.
- *
- * @return <code>true</code> if whether this <code>MinOptMax</code> doesn't allow for shrinking
- * or stretching; <code>false</code> otherwise.
- * @see #isElastic()
- */
- public boolean isStiff() {
- return min == max;
- }
-
- /**
- * Determines whether this <code>MinOptMax</code> allows for shrinking or stretching, which
- * means that at least one of the min or max values isn't equal to the opt value.
- *
- * @return <code>true</code> if this <code>MinOptMax</code> allows for shrinking or stretching;
- * <code>false</code> otherwise.
- * @see #isStiff()
- */
- public boolean isElastic() {
- return min != opt || opt != max;
- }
-
- /**
- * Extends the minimum length to the given length if necessary, and adjusts opt and max
- * accordingly.
- *
- * @param newMin the new minimum length
- * @return a <code>MinOptMax</code> instance with the minimum length extended
- */
- public MinOptMax extendMinimum(int newMin) {
- if (min < newMin) {
- int newOpt = Math.max(newMin, opt);
- int newMax = Math.max(newOpt, max);
- return getInstance(newMin, newOpt, newMax);
- } else {
- return this;
- }
- }
-
- /**
- * {@inheritDoc}
- */
- public boolean equals(Object obj) {
- if (this == obj) {
- return true;
- }
- if (obj == null || getClass() != obj.getClass()) {
- return false;
- }
-
- MinOptMax minOptMax = (MinOptMax) obj;
-
- return opt == minOptMax.opt && max == minOptMax.max && min == minOptMax.min;
- }
-
- /**
- * {@inheritDoc}
- */
- public int hashCode() {
- int result = min;
- result = 31 * result + opt;
- result = 31 * result + max;
- return result;
- }
-
- /**
- * {@inheritDoc}
- */
- public String toString() {
- return "MinOptMax[min = " + min + ", opt = " + opt + ", max = " + max + "]";
- }
- }
|