123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345 |
- /*
- * 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.fo.properties;
-
- import org.apache.fop.datatypes.CompoundDatatype;
- import org.apache.fop.datatypes.Length;
- import org.apache.fop.datatypes.PercentBaseContext;
- import org.apache.fop.fo.FObj;
- import org.apache.fop.fo.PropertyList;
- import org.apache.fop.fo.expr.PropertyException;
- import org.apache.fop.traits.MinOptMax;
- import org.apache.fop.util.CompareUtil;
-
- /**
- * Superclass for properties that contain LengthRange values
- */
- public class LengthRangeProperty extends Property implements CompoundDatatype {
- private Property minimum;
- private Property optimum;
- private Property maximum;
- private static final int MINSET = 1;
- private static final int OPTSET = 2;
- private static final int MAXSET = 4;
- private int bfSet; // bit field
- private boolean consistent;
-
- /**
- * Converts this <code>LengthRangeProperty</code> to a <code>MinOptMax</code>.
- *
- * @param context Percentage evaluation context
- * @return the requested MinOptMax instance
- */
- public MinOptMax toMinOptMax(PercentBaseContext context) {
- int min = getMinimum(context).isAuto() ? 0
- : getMinimum(context).getLength().getValue(context);
- int opt = getOptimum(context).isAuto() ? min
- : getOptimum(context).getLength().getValue(context);
- int max = getMaximum(context).isAuto() ? Integer.MAX_VALUE
- : getMaximum(context).getLength().getValue(context);
- return MinOptMax.getInstance(min, opt, max);
- }
-
- /**
- * Inner class for a Maker for LengthProperty objects
- */
- public static class Maker extends CompoundPropertyMaker {
-
- /**
- * @param propId the id of the property for which a Maker should be created
- */
- public Maker(int propId) {
- super(propId);
- }
-
- /**
- * Create a new empty instance of LengthRangeProperty.
- * @return the new instance.
- */
- public Property makeNewProperty() {
- return new LengthRangeProperty();
- }
-
- private boolean isNegativeLength(Length len) {
- return ((len instanceof PercentLength
- && ((PercentLength) len).getPercentage() < 0)
- || (len.isAbsolute() && len.getValue() < 0));
- }
-
- /** {@inheritDoc} */
- public Property convertProperty(Property p,
- PropertyList propertyList, FObj fo)
- throws PropertyException {
-
- if (p instanceof LengthRangeProperty) {
- return p;
- }
-
- if (this.propId == PR_BLOCK_PROGRESSION_DIMENSION
- || this.propId == PR_INLINE_PROGRESSION_DIMENSION) {
- Length len = p.getLength();
- if (len != null) {
- if (isNegativeLength(len)) {
- log.warn(FObj.decorateWithContextInfo(
- "Replaced negative value (" + len + ") for " + getName()
- + " with 0mpt", fo));
- p = FixedLength.ZERO_FIXED_LENGTH;
- }
- }
- }
-
- return super.convertProperty(p, propertyList, fo);
- }
-
-
- /**
- * {@inheritDoc}
- */
- protected Property setSubprop(Property baseProperty, int subpropertyId,
- Property subproperty) {
- CompoundDatatype val = (CompoundDatatype) baseProperty.getObject();
- if (this.propId == PR_BLOCK_PROGRESSION_DIMENSION
- || this.propId == PR_INLINE_PROGRESSION_DIMENSION) {
- Length len = subproperty.getLength();
- if (len != null) {
- if (isNegativeLength(len)) {
- log.warn("Replaced negative value (" + len + ") for " + getName()
- + " with 0mpt");
- val.setComponent(subpropertyId,
- FixedLength.ZERO_FIXED_LENGTH, false);
- return baseProperty;
- }
- }
- }
- val.setComponent(subpropertyId, subproperty, false);
- return baseProperty;
- }
-
- }
-
-
-
- /**
- * {@inheritDoc}
- */
- public void setComponent(int cmpId, Property cmpnValue,
- boolean bIsDefault) {
- if (cmpId == CP_MINIMUM) {
- setMinimum(cmpnValue, bIsDefault);
- } else if (cmpId == CP_OPTIMUM) {
- setOptimum(cmpnValue, bIsDefault);
- } else if (cmpId == CP_MAXIMUM) {
- setMaximum(cmpnValue, bIsDefault);
- }
- }
-
- /**
- * {@inheritDoc}
- */
- public Property getComponent(int cmpId) {
- if (cmpId == CP_MINIMUM) {
- return getMinimum(null);
- } else if (cmpId == CP_OPTIMUM) {
- return getOptimum(null);
- } else if (cmpId == CP_MAXIMUM) {
- return getMaximum(null);
- } else {
- return null; // SHOULDN'T HAPPEN
- }
- }
-
- /**
- * Set minimum value to min.
- * @param minimum A Length value specifying the minimum value for this
- * LengthRange.
- * @param bIsDefault If true, this is set as a "default" value
- * and not a user-specified explicit value.
- */
- protected void setMinimum(Property minimum, boolean bIsDefault) {
- this.minimum = minimum;
- if (!bIsDefault) {
- bfSet |= MINSET;
- }
- consistent = false;
- }
-
-
- /**
- * Set maximum value to max if it is >= optimum or optimum isn't set.
- * @param max A Length value specifying the maximum value for this
- * @param bIsDefault If true, this is set as a "default" value
- * and not a user-specified explicit value.
- */
- protected void setMaximum(Property max, boolean bIsDefault) {
- maximum = max;
- if (!bIsDefault) {
- bfSet |= MAXSET;
- }
- consistent = false;
- }
-
-
- /**
- * Set the optimum value.
- * @param opt A Length value specifying the optimum value for this
- * @param bIsDefault If true, this is set as a "default" value
- * and not a user-specified explicit value.
- */
- protected void setOptimum(Property opt, boolean bIsDefault) {
- optimum = opt;
- if (!bIsDefault) {
- bfSet |= OPTSET;
- }
- consistent = false;
- }
-
- // Minimum is prioritaire, if explicit
- private void checkConsistency(PercentBaseContext context) {
- if (consistent) {
- return;
- }
- if (context == null) {
- return;
- }
- // Make sure max >= min
- // Must also control if have any allowed enum values!
-
- if (!minimum.isAuto() && !maximum.isAuto()
- && minimum.getLength().getValue(context) > maximum.getLength().getValue(context)) {
- if ((bfSet & MINSET) != 0) {
- // if minimum is explicit, force max to min
- if ((bfSet & MAXSET) != 0) {
- // Warning: min>max, resetting max to min
- log.error("forcing max to min in LengthRange");
- }
- maximum = minimum;
- } else {
- minimum = maximum; // minimum was default value
- }
- }
- // Now make sure opt <= max and opt >= min
- if (!optimum.isAuto() && !maximum.isAuto()
- && optimum.getLength().getValue(context) > maximum.getLength().getValue(context)) {
- if ((bfSet & OPTSET) != 0) {
- if ((bfSet & MAXSET) != 0) {
- // Warning: opt > max, resetting opt to max
- log.error("forcing opt to max in LengthRange");
- optimum = maximum;
- } else {
- maximum = optimum; // maximum was default value
- }
- } else {
- // opt is default and max is explicit or default
- optimum = maximum;
- }
- } else if (!optimum.isAuto() && !minimum.isAuto()
- && optimum.getLength().getValue(context)
- < minimum.getLength().getValue(context)) {
- if ((bfSet & MINSET) != 0) {
- // if minimum is explicit, force opt to min
- if ((bfSet & OPTSET) != 0) {
- log.error("forcing opt to min in LengthRange");
- }
- optimum = minimum;
- } else {
- minimum = optimum; // minimum was default value
- }
- }
-
- consistent = true;
- }
-
- /**
- * @param context Percentage evaluation context
- * @return minimum length
- */
- public Property getMinimum(PercentBaseContext context) {
- checkConsistency(context);
- return this.minimum;
- }
-
- /**
- * @param context Percentage evaluation context
- * @return maximum length
- */
- public Property getMaximum(PercentBaseContext context) {
- checkConsistency(context);
- return this.maximum;
- }
-
- /**
- * @param context Percentage evaluation context
- * @return optimum length
- */
- public Property getOptimum(PercentBaseContext context) {
- checkConsistency(context);
- return this.optimum;
- }
-
- /** {@inheritDoc} */
- public String toString() {
- return "LengthRange["
- + "min:" + getMinimum(null).getObject()
- + ", max:" + getMaximum(null).getObject()
- + ", opt:" + getOptimum(null).getObject() + "]";
- }
-
- /**
- * @return this.lengthRange
- */
- public LengthRangeProperty getLengthRange() {
- return this;
- }
-
- /**
- * @return this.lengthRange cast as an Object
- */
- public Object getObject() {
- return this;
- }
-
- @Override
- public int hashCode() {
- final int prime = 31;
- int result = 1;
- result = prime * result + bfSet;
- result = prime * result + (consistent ? 1231 : 1237);
- result = prime * result + CompareUtil.getHashCode(minimum);
- result = prime * result + CompareUtil.getHashCode(optimum);
- result = prime * result + CompareUtil.getHashCode(maximum);
- return result;
- }
-
- @Override
- public boolean equals(Object obj) {
- if (this == obj) {
- return true;
- }
- if (!(obj instanceof LengthRangeProperty)) {
- return false;
- }
- LengthRangeProperty other = (LengthRangeProperty) obj;
- return bfSet == other.bfSet
- && consistent == other.consistent
- && CompareUtil.equal(minimum, other.minimum)
- && CompareUtil.equal(optimum, other.optimum)
- && CompareUtil.equal(maximum, other.maximum);
- }
- }
|