/*
* Copyright 1999-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.area;
import java.io.Serializable;
import java.util.Map;
import java.util.HashMap;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.apache.fop.datatypes.ColorType;
import org.apache.fop.traits.BorderProps;
// If the area appears more than once in the output
// or if the area has external data it is cached
// to keep track of it and to minimize rendered output
// renderers can render the output once and display it
// for every occurence
// this should also extend to all outputs (including PDFGraphics2D)
// and all types of renderers
/**
* Base object for all areas.
*/
public class Area implements Serializable {
// stacking directions
/**
* Stacking left to right
*/
public static final int LR = 0;
/**
* Stacking right to left
*/
public static final int RL = 1;
/**
* Stacking top to bottom
*/
public static final int TB = 2;
/**
* Stacking bottom to top
*/
public static final int BT = 3;
// orientations for reference areas
/**
* Normal orientation
*/
public static final int ORIENT_0 = 0;
/**
* Rotated 90 degrees clockwise
*/
public static final int ORIENT_90 = 1;
/**
* Rotate 180 degrees
*/
public static final int ORIENT_180 = 2;
/**
* Rotated 270 degrees clockwise
*/
public static final int ORIENT_270 = 3;
// area class values
/**
* Normal class
*/
public static final int CLASS_NORMAL = 0;
/**
* Fixed position class
*/
public static final int CLASS_FIXED = 1;
/**
* Absolute position class
*/
public static final int CLASS_ABSOLUTE = 2;
/**
* Before float class
*/
public static final int CLASS_BEFORE_FLOAT = 3;
/**
* Footnote class
*/
public static final int CLASS_FOOTNOTE = 4;
/**
* Side float class
*/
public static final int CLASS_SIDE_FLOAT = 5;
// IMPORTANT: make sure this is the maximum + 1
/**
* Maximum class count
*/
public static final int CLASS_MAX = CLASS_SIDE_FLOAT + 1;
private int areaClass = CLASS_NORMAL;
/** the area's inline-progression-dimension */
protected int ipd;
/** the area's block-progression-dimension */
protected int bpd;
/**
* Traits for this area stored in a HashMap
*/
protected HashMap props = null;
/**
* logging instance
*/
protected static Log log = LogFactory.getLog(Area.class);
/**
* Get the area class of this area.
*
* @return the area class
*/
public int getAreaClass() {
return areaClass;
}
/**
* Set the area class of this area.
*
* @param areaClass the area class
*/
public void setAreaClass(int areaClass) {
this.areaClass = areaClass;
}
/**
* Set the inline progression dimension of content rectangle
* for this area.
*
* @param i the new inline progression dimension
* @see ipd
*/
public void setIPD(int i) {
ipd = i;
}
/**
* Get the inline progression dimension of the content rectangle
* for this area.
*
* @return the inline progression dimension
* @see ipd
*/
public int getIPD() {
return ipd;
}
/**
* Set the block progression dimension of the content rectangle
* for this area.
*
* @param b the new block progression dimension
* @see bpd
*/
public void setBPD(int b) {
bpd = b;
}
/**
* Get the block progression dimension of the content rectangle
* for this area.
*
* @return the block progression dimension
* @see bpd
*/
public int getBPD() {
return bpd;
}
/**
* Get the allocation inline progression dimension of this area.
* This adds the content, borders and the padding to find the
* total allocated IPD.
*
* @return the total IPD allocation for this area
*/
public int getAllocIPD() {
return getBorderAndPaddingWidthStart() + getIPD() + getBorderAndPaddingWidthEnd();
}
/**
* Get the allocation block progression dimension of this area.
* This adds the content, borders, padding and spaces to find the
* total allocated BPD.
*
* @return the total BPD allocation for this area
*/
public int getAllocBPD() {
return getSpaceBefore() + getBorderAndPaddingWidthBefore() + getBPD()
+ getBorderAndPaddingWidthAfter() + getSpaceAfter();
}
/**
* Return the sum of region border- and padding-before
*
* @return width in millipoints
*/
public int getBorderAndPaddingWidthBefore() {
int margin = 0;
BorderProps bps = (BorderProps) getTrait(Trait.BORDER_BEFORE);
if (bps != null) {
margin = bps.width;
}
Integer padWidth = (Integer) getTrait(Trait.PADDING_BEFORE);
if (padWidth != null) {
margin += padWidth.intValue();
}
return margin;
}
/**
* Return the sum of region border- and padding-after
*
* @return width in millipoints
*/
public int getBorderAndPaddingWidthAfter() {
int margin = 0;
BorderProps bps = (BorderProps) getTrait(Trait.BORDER_AFTER);
if (bps != null) {
margin = bps.width;
}
Integer padWidth = (Integer) getTrait(Trait.PADDING_AFTER);
if (padWidth != null) {
margin += padWidth.intValue();
}
return margin;
}
/**
* Return the sum of region border- and padding-start
*
* @return width in millipoints
*/
public int getBorderAndPaddingWidthStart() {
int margin = 0;
BorderProps bps = (BorderProps) getTrait(Trait.BORDER_START);
if (bps != null) {
margin = bps.width;
}
Integer padWidth = (Integer) getTrait(Trait.PADDING_START);
if (padWidth != null) {
margin += padWidth.intValue();
}
return margin;
}
/**
* Return the sum of region border- and padding-end
*
* @return width in millipoints
*/
public int getBorderAndPaddingWidthEnd() {
int margin = 0;
BorderProps bps = (BorderProps) getTrait(Trait.BORDER_END);
if (bps != null) {
margin = bps.width;
}
Integer padWidth = (Integer) getTrait(Trait.PADDING_END);
if (padWidth != null) {
margin += padWidth.intValue();
}
return margin;
}
/**
* Returns the space before
*
* @return width in millipoints
*/
public int getSpaceBefore() {
int margin = 0;
Integer space = (Integer) getTrait(Trait.SPACE_BEFORE);
if (space != null) {
margin = space.intValue();
}
return margin;
}
/**
* Returns the space after
*
* @return width in millipoints
*/
public int getSpaceAfter() {
int margin = 0;
Integer space = (Integer) getTrait(Trait.SPACE_AFTER);
if (space != null) {
margin = space.intValue();
}
return margin;
}
/**
* Returns the space start
*
* @return width in millipoints
*/
public int getSpaceStart() {
int margin = 0;
Integer space = (Integer) getTrait(Trait.SPACE_START);
if (space != null) {
margin = space.intValue();
}
return margin;
}
/**
* Returns the space end
*
* @return width in millipoints
*/
public int getSpaceEnd() {
int margin = 0;
Integer space = (Integer) getTrait(Trait.SPACE_END);
if (space != null) {
margin = space.intValue();
}
return margin;
}
/**
* Add a child to this area.
* The default is to do nothing. Subclasses must override
* to do something if they can have child areas.
*
* @param child the child area to add
*/
public void addChildArea(Area child) {
}
/**
* Add a trait property to this area.
*
* @param prop the Trait to add
*/
public void addTrait(Trait prop) {
if (props == null) {
props = new java.util.HashMap(20);
}
props.put(prop.getPropType(), prop.getData());
}
/**
* Add a trait to this area.
*
* @param traitCode the trait key
* @param prop the value of the trait
*/
public void addTrait(Object traitCode, Object prop) {
if (props == null) {
props = new java.util.HashMap(20);
}
if (prop instanceof ColorType) {
props.put(traitCode, Trait.Color.makeSerializable((ColorType)prop));
} else {
props.put(traitCode, prop);
}
}
/**
* Get the map of all traits on this area.
*
* @return the map of traits
*/
public Map getTraits() {
return this.props;
}
/** @return true if the area has traits */
public boolean hasTraits() {
return (this.props != null);
}
/**
* Get a trait from this area.
*
* @param oTraitCode the trait key
* @return the trait value
*/
public Object getTrait(Object oTraitCode) {
return (props != null ? props.get(oTraitCode) : null);
}
/**
* Checks whether a certain trait is set on this area.
* @param oTraitCode the trait key
* @return true if the trait is set
*/
public boolean hasTrait(Object oTraitCode) {
return (getTrait(oTraitCode) != null);
}
/**
* Get a boolean trait from this area.
* @param oTraitCode the trait key
* @return the trait value
*/
public boolean getBooleanTrait(Object oTraitCode) {
final Object obj = getTrait(oTraitCode);
if (obj instanceof Boolean) {
return ((Boolean)obj).booleanValue();
} else {
return false;
}
}
/**
* Get a trait from this area as an integer.
*
* @param oTraitCode the trait key
* @return the trait value
*/
public int getTraitAsInteger(Object oTraitCode) {
final Object obj = getTrait(oTraitCode);
if (obj instanceof Integer) {
return ((Integer)obj).intValue();
} else {
throw new IllegalArgumentException("Trait "
+ oTraitCode.getClass().getName()
+ " could not be converted to an integer");
}
}
/** @see java.lang.Object#toString() */
public String toString() {
StringBuffer sb = new StringBuffer(super.toString());
sb.append(" {ipd=").append(Integer.toString(getIPD()));
sb.append(", bpd=").append(Integer.toString(getBPD()));
sb.append("}");
return sb.toString();
}
}