/*
 * 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: LengthRangeProperty.java 1805173 2017-08-16 10:50:04Z ssteiner $ */

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
/** * 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 LengthRangeProperty to a MinOptMax.
Params:
  • context – Percentage evaluation context
Returns:the requested MinOptMax instance
/** * 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
/** * Inner class for a Maker for LengthProperty objects */
public static class Maker extends CompoundPropertyMaker {
Params:
  • propId – the id of the property for which a Maker should be created
/** * @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.
Returns:the new instance.
/** * 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}
/** {@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}
/** * {@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}
/** * {@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}
/** * {@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.
Params:
  • minimum – A Length value specifying the minimum value for this LengthRange.
  • bIsDefault – If true, this is set as a "default" value and not a user-specified explicit value.
/** * 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.
Params:
  • max – A Length value specifying the maximum value for this
  • bIsDefault – If true, this is set as a "default" value and not a user-specified explicit value.
/** * Set maximum value to max if it is &gt;= 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.
Params:
  • opt – A Length value specifying the optimum value for this
  • bIsDefault – If true, this is set as a "default" value and not a user-specified explicit value.
/** * 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; }
Params:
  • context – Percentage evaluation context
Returns:minimum length
/** * @param context Percentage evaluation context * @return minimum length */
public Property getMinimum(PercentBaseContext context) { checkConsistency(context); return this.minimum; }
Params:
  • context – Percentage evaluation context
Returns:maximum length
/** * @param context Percentage evaluation context * @return maximum length */
public Property getMaximum(PercentBaseContext context) { checkConsistency(context); return this.maximum; }
Params:
  • context – Percentage evaluation context
Returns:optimum length
/** * @param context Percentage evaluation context * @return optimum length */
public Property getOptimum(PercentBaseContext context) { checkConsistency(context); return this.optimum; }
{@inheritDoc}
/** {@inheritDoc} */
public String toString() { return "LengthRange[" + "min:" + getMinimum(null).getObject() + ", max:" + getMaximum(null).getObject() + ", opt:" + getOptimum(null).getObject() + "]"; }
Returns:this.lengthRange
/** * @return this.lengthRange */
public LengthRangeProperty getLengthRange() { return this; }
Returns:this.lengthRange cast as an Object
/** * @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); } }