diff --git a/openpdf/src/main/java/com/lowagie/text/HeaderFooter.java b/openpdf/src/main/java/com/lowagie/text/HeaderFooter.java
index 5b4e8b181..9faa5d805 100644
--- a/openpdf/src/main/java/com/lowagie/text/HeaderFooter.java
+++ b/openpdf/src/main/java/com/lowagie/text/HeaderFooter.java
@@ -49,81 +49,105 @@
package com.lowagie.text;
+import java.util.ArrayList;
+import java.util.List;
+
+import com.lowagie.text.pdf.PdfPTable;
/**
- * A HeaderFooter-object is a Rectangle with text
- * that can be put above and/or below every page.
- *
- * Example: - *
*/ public class HeaderFooter extends Rectangle { - + // membervariables - -/** Does the page contain a pagenumber? */ + + /** + * Does the page contain a pagenumber? + */ private boolean numbered; - -/** This is the+ * A+ * + *HeaderFooter-object is aRectanglewith text that can be put above and/or below every + * page. + *+ * Example:
+ * + *+ ** HeaderFooter header = new HeaderFooter(new Phrase("This is a header."), false); * HeaderFooter footer = new HeaderFooter(new Phrase("This is page "), new Phrase(".")); * document.setHeader(header); * document.setFooter(footer); - *
Phrase that comes before the pagenumber. */
+
+ /**
+ * This is the Phrase that comes before the pagenumber.
+ */
private Phrase before = null;
-
-/** This is number of the page. */
+
+ /**
+ * This is number of the page.
+ */
private int pageN;
-
-/** This is the Phrase that comes after the pagenumber. */
+
+ /**
+ * This is the Phrase that comes after the pagenumber.
+ */
private Phrase after = null;
-
-/** This is alignment of the header/footer. */
+
+ /**
+ * This is alignment of the header/footer.
+ */
private int alignment;
-
+
+ /**
+ * This is the List containing non-text Element.
+ */
+ private java.util.ListHeaderFooter-object.
- *
- * @param before the Phrase before the pagenumber
- * @param after the Phrase before the pagenumber
- */
-
+
+ /**
+ * Constructs a HeaderFooter-object.
+ *
+ * @param before the Phrase before the pagenumber
+ * @param after the Phrase before the pagenumber
+ */
public HeaderFooter(Phrase before, Phrase after) {
super(0, 0, 0, 0);
setBorder(TOP + BOTTOM);
setBorderWidth(1);
-
+
numbered = true;
this.before = before;
this.after = after;
}
-
-/**
- * Constructs a Header-object with a pagenumber at the end.
- *
- * @param before the Phrase before the pagenumber
- * @param numbered page will be numbered if true
- */
-
+
+ /**
+ * Constructs a Header-object with a pagenumber at the end.
+ *
+ * @param before the Phrase before the pagenumber
+ * @param numbered page will be numbered if true
+ */
public HeaderFooter(Phrase before, boolean numbered) {
super(0, 0, 0, 0);
setBorder(TOP + BOTTOM);
setBorderWidth(1);
-
+
this.numbered = numbered;
this.before = before;
}
-/**
- * Constructs a Header-object with a pagenumber at the beginning.
- *
- * @param numbered page will be numbered if true
- * @param after the Phrase after the pagenumber
- */
-
+ /**
+ * Constructs a Header-object with a pagenumber at the beginning.
+ *
+ * @param numbered page will be numbered if true
+ * @param after the Phrase after the pagenumber
+ */
public HeaderFooter(boolean numbered, Phrase after) {
super(0, 0, 0, 0);
setBorder(TOP + BOTTOM);
@@ -133,82 +157,133 @@ public HeaderFooter(boolean numbered, Phrase after) {
this.after = after;
}
-/**
- * Constructs a Header-object with only a pagenumber.
- *
- * @param numbered true if the page has to be numbered
- */
-
+ /**
+ * Constructs a Header-object with only a pagenumber.
+ *
+ * @param numbered true if the page has to be numbered
+ */
public HeaderFooter(boolean numbered) {
this(null, true);
this.numbered = numbered;
}
// methods
-
-/**
- * Checks if the HeaderFooter contains a page number.
- *
- * @return true if the page has to be numbered
- */
-
+
+ /**
+ * Checks if the HeaderFooter contains a page number.
+ *
+ * @return true if the page has to be numbered
+ */
public boolean isNumbered() {
return numbered;
}
-
-/**
- * Gets the part that comes before the pageNumber.
- *
- * @return a Phrase
- */
-
+
+ /**
+ * Gets the part that comes before the pageNumber.
+ *
+ * @return a Phrase
+ */
public Phrase getBefore() {
return before;
}
-
-/**
- * Gets the part that comes after the pageNumber.
- *
- * @return a Phrase
- */
-
+
+ /**
+ * Gets the part that comes after the pageNumber.
+ *
+ * @return a Phrase
+ */
public Phrase getAfter() {
return after;
}
-
-/**
- * Sets the page number.
- *
- * @param pageN the new page number
- */
-
+
+ /**
+ * Sets the page number.
+ *
+ * @param pageN the new page number
+ */
public void setPageNumber(int pageN) {
this.pageN = pageN;
}
-
-/**
- * Sets the alignment.
- *
- * @param alignment the new alignment
- */
-
+
+ /**
+ * Sets the alignment.
+ *
+ * @param alignment the new alignment
+ */
public void setAlignment(int alignment) {
this.alignment = alignment;
}
+ /**
+ * Gets padding of height of header/footer.
+ *
+ * @return the padding of height
+ */
+ public float getPadding() {
+ return padding;
+ }
+
+ /**
+ * Sets padding of height of header/footer.
+ *
+ * @param padding the new padding of height
+ */
+ public void setPadding(float padding) {
+ this.padding = padding;
+ }
+
+ /**
+ * Increases current padding by adding new value into it
+ *
+ * @param augment the new value
+ */
+ public void addPadding(float augment) {
+ padding += augment;
+ }
+
+ /**
+ * Adds non-text Element into specialContent
+ *
+ * @param element the new non-text Element
+ */
+ public void addSpecialContent(Element element) {
+ if (specialContent == null) {
+ specialContent = new ArrayList<>();
+ }
+ specialContent.add(element);
+ }
+
+ /**
+ * Gets specialContent
+ *
+ * @return specialContent
+ */
+ public ListParagraph that can be used as header or footer.
- *
- * @return a Paragraph
- */
-
+
+ /**
+ * Gets the Paragraph that can be used as header or footer.
+ *
+ * @return a Paragraph
+ */
public Paragraph paragraph() {
Paragraph paragraph;
+
if (before != null) {
paragraph = new Paragraph(before.getLeading());
paragraph.add(before);
+
+ // Adding a Paragraph to another Paraghraph adds a newline that needs to be removed in headers and footers
+ if (before instanceof Paragraph
+ &&
+ paragraph.size() >= 2
+ &&
+ "\n".equals(paragraph.get(paragraph.size() - 1).toString())) {
+ paragraph.remove(paragraph.size() - 1);
+ }
} else {
paragraph = new Paragraph();
}
@@ -221,10 +296,13 @@ public Paragraph paragraph() {
paragraph.addSpecial(new Chunk(String.valueOf(pageN)));
}
}
+
if (after != null) {
paragraph.addSpecial(after);
}
+
paragraph.setAlignment(alignment);
+
return paragraph;
}
@@ -232,6 +310,7 @@ private Font getFont() {
if (before != null) {
return before.getFont();
}
+
if (after != null) {
return after.getFont();
}
@@ -242,11 +321,9 @@ private Font getFont() {
/**
* Gets the alignment of this HeaderFooter.
*
- * @return alignment
+ * @return alignment
*/
-
- public int alignment() {
- return alignment;
- }
-
+ public int alignment() {
+ return alignment;
+ }
}
\ No newline at end of file
diff --git a/openpdf/src/main/java/com/lowagie/text/Rectangle.java b/openpdf/src/main/java/com/lowagie/text/Rectangle.java
index c1238d0af..d93a2719b 100644
--- a/openpdf/src/main/java/com/lowagie/text/Rectangle.java
+++ b/openpdf/src/main/java/com/lowagie/text/Rectangle.java
@@ -55,13 +55,13 @@
/**
* A Rectangle is the representation of a geometric figure.
- *
+ *
* Rectangles support constant width borders using
* {@link #setBorderWidth(float)}and {@link #setBorder(int)}. They also support
* borders that vary in width/color on each side using methods like
* {@link #setBorderWidthLeft(float)}or
* {@link #setBorderColorLeft(java.awt.Color)}.
- *
+ *
* @see Element
* @see Table
* @see Cell
@@ -69,904 +69,913 @@
*/
public class Rectangle implements Element {
- // CONSTANTS:
+ // CONSTANTS:
+
+ /** This is the value that will be used as undefined . */
+ public static final int UNDEFINED = -1;
+
+ /** This represents one side of the border of the Rectangle. */
+ public static final int TOP = 1;
+
+ /** This represents one side of the border of the Rectangle. */
+ public static final int BOTTOM = 2;
+
+ /** This represents one side of the border of the Rectangle. */
+ public static final int LEFT = 4;
+
+ /** This represents one side of the border of the Rectangle. */
+ public static final int RIGHT = 8;
+
+ /** This represents a rectangle without borders. */
+ public static final int NO_BORDER = 0;
+
+ /** This represents a type of border. */
+ public static final int BOX = TOP + BOTTOM + LEFT + RIGHT;
+
+ // MEMBER VARIABLES:
+
+ /** the lower left x-coordinate. */
+ protected float llx;
+
+ /** the lower left y-coordinate. */
+ protected float lly;
+
+ /** the upper right x-coordinate. */
+ protected float urx;
+
+ /** the upper right y-coordinate. */
+ protected float ury;
+
+ protected float aFloat;
+
+ /** The rotation of the Rectangle */
+ protected int rotation = 0;
+
+ /** This is the color of the background of this rectangle. */
+ protected Color backgroundColor = null;
+
+ /** This represents the status of the 4 sides of the rectangle. */
+ protected int border = UNDEFINED;
+
+ /** Whether variable width/color borders are used. */
+ protected boolean useVariableBorders = false;
+
+ /** This is the width of the border around this rectangle. */
+ protected float borderWidth = UNDEFINED;
+
+ /** The width of the left border of this rectangle. */
+ protected float borderWidthLeft = UNDEFINED;
+
+ /** The width of the right border of this rectangle. */
+ protected float borderWidthRight = UNDEFINED;
+
+ /** The width of the top border of this rectangle. */
+ protected float borderWidthTop = UNDEFINED;
+
+ /** The width of the bottom border of this rectangle. */
+ protected float borderWidthBottom = UNDEFINED;
+
+ /** The color of the border of this rectangle. */
+ protected Color borderColor = null;
+
+ /** The color of the left border of this rectangle. */
+ protected Color borderColorLeft = null;
+
+ /** The color of the right border of this rectangle. */
+ protected Color borderColorRight = null;
+
+ /** The color of the top border of this rectangle. */
+ protected Color borderColorTop = null;
+
+ /** The color of the bottom border of this rectangle. */
+ protected Color borderColorBottom = null;
+
+ // CONSTRUCTORS:
+
+ /**
+ * Constructs a Rectangle -object.
+ *
+ * @param llx
+ * lower left x
+ * @param lly
+ * lower left y
+ * @param urx
+ * upper right x
+ * @param ury
+ * upper right y
+ */
+ public Rectangle(float llx, float lly, float urx, float ury) {
+ this.llx = llx;
+ this.lly = lly;
+ this.urx = urx;
+ this.ury = ury;
+ }
+
+ /**
+ * Constructs a Rectangle -object starting from the origin (0,
+ * 0).
+ *
+ * @param urx
+ * upper right x
+ * @param ury
+ * upper right y
+ */
+ public Rectangle(float urx, float ury) {
+ this(0, 0, urx, ury);
+ }
+
+ // OJO... Modificacion de
+ // flopez-------------------------------------------------
+ /**
+ * Constructs a Rectangle -object.
+ *
+ * @param llx
+ * lower left x
+ * @param lly
+ * lower left y
+ * @param urx
+ * upper right x
+ * @param ury
+ * upper right y
+ * @param rotation
+ * 0, 90, 180, or 270 grades
+ */
+ public Rectangle(float llx, float lly, float urx, float ury, int rotation) {
+ this(llx, lly, urx, ury);
+ setRotation(rotation);
+ }
+
+ /**
+ * Constructs a Rectangle -object starting from the origin (0,
+ * 0).
+ *
+ * @param urx
+ * upper right x
+ * @param ury
+ * upper right y
+ * @param rotation
+ * 0, 90, 180, or 270 grades
+ */
+ public Rectangle(float urx, float ury, int rotation) {
+ this(0, 0, urx, ury);
+ setRotation(rotation);
+ }
+
+ /**
+ * Sets the rotation of the rectangle. Valid values are 0, 90, 180, and 270.
+ *
+ * @param rotation
+ * the new rotation value
+ * @since iText 5.0.6
+ */
+ public void setRotation(final int rotation) {
+ int mod = rotation % 360;
+ if ((mod == 90) || (mod == 180) || (mod == 270)) {
+ this.rotation = mod;
+ } else {
+ this.rotation = 0;
+ }
+ }
+
+ // ******************************************************************************
+
+ /**
+ * Constructs a Rectangle -object.
+ *
+ * @param rect
+ * another Rectangle
+ */
+ public Rectangle(Rectangle rect) {
+ this(rect.llx, rect.lly, rect.urx, rect.ury);
+ cloneNonPositionParameters(rect);
+ }
- /** This is the value that will be used as undefined . */
- public static final int UNDEFINED = -1;
+ // IMPLEMENTATION OF THE ELEMENT INTERFACE:e
+
+ /**
+ * Processes the element by adding it (or the different parts) to an
+ * ElementListener.
+ *
+ * @param listener
+ * an ElementListener
+ * @return true if the element was processed successfully
+ */
+ @Override
+ public boolean process(ElementListener listener) {
+ try {
+ return listener.add(this);
+ } catch (DocumentException de) {
+ return false;
+ }
+ }
- /** This represents one side of the border of the Rectangle. */
- public static final int TOP = 1;
+ /**
+ * Gets the type of the text element.
+ *
+ * @return a type
+ */
+ @Override
+ public int type() {
+ return Element.RECTANGLE;
+ }
- /** This represents one side of the border of the Rectangle. */
- public static final int BOTTOM = 2;
+ /**
+ * Gets all the chunks in this element.
+ *
+ * @return an ArrayList
+ */
+ @Override
+ public ArrayListRectangle. */
- public static final int LEFT = 4;
+ /**
+ * @see com.lowagie.text.Element#isContent()
+ * @since iText 2.0.8
+ */
+ @Override
+ public boolean isContent() {
+ return true;
+ }
- /** This represents one side of the border of the Rectangle. */
- public static final int RIGHT = 8;
+ /**
+ * @see com.lowagie.text.Element#isNestable()
+ * @since iText 2.0.8
+ */
+ @Override
+ public boolean isNestable() {
+ return false;
+ }
- /** This represents a rectangle without borders. */
- public static final int NO_BORDER = 0;
+ // METHODS TO GET/SET THE DIMENSIONS:
- /** This represents a type of border. */
- public static final int BOX = TOP + BOTTOM + LEFT + RIGHT;
+ /**
+ * Sets the lower left x-coordinate.
+ *
+ * @param llx
+ * the new value
+ */
+ public void setLeft(float llx) {
+ this.llx = llx;
+ }
- // MEMBER VARIABLES:
+ /**
+ * Returns the lower left x-coordinate.
+ *
+ * @return the lower left x-coordinate
+ */
+ public float getLeft() {
+ return llx;
+ }
- /** the lower left x-coordinate. */
- protected float llx;
-
- /** the lower left y-coordinate. */
- protected float lly;
-
- /** the upper right x-coordinate. */
- protected float urx;
-
- /** the upper right y-coordinate. */
- protected float ury;
-
- /** The rotation of the Rectangle */
- protected int rotation = 0;
-
- /** This is the color of the background of this rectangle. */
- protected Color backgroundColor = null;
-
- /** This represents the status of the 4 sides of the rectangle. */
- protected int border = UNDEFINED;
-
- /** Whether variable width/color borders are used. */
- protected boolean useVariableBorders = false;
-
- /** This is the width of the border around this rectangle. */
- protected float borderWidth = UNDEFINED;
-
- /** The width of the left border of this rectangle. */
- protected float borderWidthLeft = UNDEFINED;
-
- /** The width of the right border of this rectangle. */
- protected float borderWidthRight = UNDEFINED;
-
- /** The width of the top border of this rectangle. */
- protected float borderWidthTop = UNDEFINED;
-
- /** The width of the bottom border of this rectangle. */
- protected float borderWidthBottom = UNDEFINED;
-
- /** The color of the border of this rectangle. */
- protected Color borderColor = null;
-
- /** The color of the left border of this rectangle. */
- protected Color borderColorLeft = null;
-
- /** The color of the right border of this rectangle. */
- protected Color borderColorRight = null;
-
- /** The color of the top border of this rectangle. */
- protected Color borderColorTop = null;
-
- /** The color of the bottom border of this rectangle. */
- protected Color borderColorBottom = null;
-
- // CONSTRUCTORS:
-
- /**
- * Constructs a Rectangle -object.
- *
- * @param llx
- * lower left x
- * @param lly
- * lower left y
- * @param urx
- * upper right x
- * @param ury
- * upper right y
- */
- public Rectangle(float llx, float lly, float urx, float ury) {
- this.llx = llx;
- this.lly = lly;
- this.urx = urx;
- this.ury = ury;
- }
-
- /**
- * Constructs a Rectangle -object starting from the origin (0,
- * 0).
- *
- * @param urx
- * upper right x
- * @param ury
- * upper right y
- */
- public Rectangle(float urx, float ury) {
- this(0, 0, urx, ury);
- }
-
- // OJO... Modificacion de
- // flopez-------------------------------------------------
- /**
- * Constructs a Rectangle -object.
- *
- * @param llx
- * lower left x
- * @param lly
- * lower left y
- * @param urx
- * upper right x
- * @param ury
- * upper right y
- * @param rotation
- * 0, 90, 180, or 270 grades
- */
- public Rectangle(float llx, float lly, float urx, float ury, int rotation) {
- this(llx, lly, urx, ury);
- setRotation(rotation);
- }
-
- /**
- * Constructs a Rectangle -object starting from the origin (0,
- * 0).
- *
- * @param urx
- * upper right x
- * @param ury
- * upper right y
- * @param rotation
- * 0, 90, 180, or 270 grades
- */
- public Rectangle(float urx, float ury, int rotation) {
- this(0, 0, urx, ury);
- setRotation(rotation);
- }
-
- /**
- * Sets the rotation of the rectangle. Valid values are 0, 90, 180, and 270.
- *
- * @param rotation
- * the new rotation value
- * @since iText 5.0.6
- */
- public void setRotation(final int rotation) {
- int mod = rotation % 360;
- if ((mod == 90) || (mod == 180) || (mod == 270)) {
- this.rotation = mod;
- } else {
- this.rotation = 0;
- }
- }
-
- // ******************************************************************************
-
- /**
- * Constructs a Rectangle -object.
- *
- * @param rect
- * another Rectangle
- */
- public Rectangle(Rectangle rect) {
- this(rect.llx, rect.lly, rect.urx, rect.ury);
- cloneNonPositionParameters(rect);
- }
-
- // IMPLEMENTATION OF THE ELEMENT INTERFACE:e
-
- /**
- * Processes the element by adding it (or the different parts) to an
- * ElementListener.
- *
- * @param listener
- * an ElementListener
- * @return true if the element was processed successfully
- */
- @Override
- public boolean process(ElementListener listener) {
- try {
- return listener.add(this);
- } catch (DocumentException de) {
- return false;
- }
- }
-
- /**
- * Gets the type of the text element.
- *
- * @return a type
- */
- @Override
- public int type() {
- return Element.RECTANGLE;
- }
-
- /**
- * Gets all the chunks in this element.
- *
- * @return an ArrayList
- */
- @Override
- public ArrayListRectangle
- */
- public Rectangle rotate() {
- Rectangle rect = new Rectangle(lly, llx, ury, urx);
- rect.rotation = rotation + 90;
- rect.rotation %= 360;
- return rect;
- }
-
- // METHODS TO GET/SET THE BACKGROUND COLOR:
-
- /**
- * Gets the backgroundcolor.
- *
- * @return a Color
- */
- public Color getBackgroundColor() {
- return backgroundColor;
- }
-
- /**
- * Sets the backgroundcolor of the rectangle.
- *
- * @param backgroundColor
- * a Color
- */
-
- public void setBackgroundColor(Color backgroundColor) {
- this.backgroundColor = backgroundColor;
- }
-
- /**
- * Gets the grayscale.
- *
- * @return the grayscale color of the background or 0 if the background has no
- * grayscale color.
- */
- public float getGrayFill() {
- if (backgroundColor instanceof GrayColor)
- return ((GrayColor) backgroundColor).getGray();
- return 0;
- }
-
- /**
- * Sets the the background color to a grayscale value.
- *
- * @param value
- * the new grayscale value
- */
- public void setGrayFill(float value) {
- backgroundColor = new GrayColor(value);
- }
-
- // METHODS TO GET/SET THE BORDER:
-
- /**
- * Returns the exact type of the border.
- *
- * @return a value
- */
- public int getBorder() {
- return border;
- }
-
- /**
- * Indicates whether some type of border is set.
- *
- * @return a boolean
- */
- public boolean hasBorders() {
- switch (border) {
- case UNDEFINED:
- case NO_BORDER:
- return false;
- default:
- return borderWidth > 0 || borderWidthLeft > 0 || borderWidthRight > 0
- || borderWidthTop > 0 || borderWidthBottom > 0;
- }
- }
-
- /**
- * Indicates whether the specified type of border is set.
- *
- * @param type
- * the type of border
- * @return a boolean
- */
- public boolean hasBorder(int type) {
- if (border == UNDEFINED)
- return false;
- return (border & type) == type;
- }
-
- /**
- * Enables/Disables the border on the specified sides. The border is specified
- * as an integer bitwise combination of the constants:
- * LEFT, RIGHT, TOP, BOTTOM.
- *
- * @see #enableBorderSide(int)
- * @see #disableBorderSide(int)
- * @param border
- * the new value
- */
- public void setBorder(int border) {
- this.border = border;
- }
-
- /**
- * Indicates whether variable width borders are being used. Returns true if
- * setBorderWidthLeft, setBorderWidthRight,
- * setBorderWidthTop, or setBorderWidthBottom has been called.
- *
- * @return true if variable width borders are in use
- */
- public boolean isUseVariableBorders() {
- return useVariableBorders;
- }
-
- /**
- * Sets a parameter indicating if the rectangle has variable borders
- *
- * @param useVariableBorders
- * indication if the rectangle has variable borders
- */
- public void setUseVariableBorders(boolean useVariableBorders) {
- this.useVariableBorders = useVariableBorders;
- }
-
- /**
- * Enables the border on the specified side.
- *
- * @param side
- * the side to enable. One of LEFT, RIGHT, TOP, BOTTOM
- */
- public void enableBorderSide(int side) {
- if (border == UNDEFINED)
- border = 0;
- border |= side;
- }
-
- /**
- * Disables the border on the specified side.
- *
- * @param side
- * the side to disable. One of LEFT, RIGHT, TOP, BOTTOM
- */
- public void disableBorderSide(int side) {
- if (border == UNDEFINED)
- border = 0;
- border &= ~side;
- }
-
- // METHODS TO GET/SET THE BORDER WIDTH:
-
- /**
- * Gets the borderwidth.
- *
- * @return a value
- */
- public float getBorderWidth() {
- return borderWidth;
- }
-
- /**
- * Sets the borderwidth of the table.
- *
- * @param borderWidth
- * the new value
- */
- public void setBorderWidth(float borderWidth) {
- this.borderWidth = borderWidth;
- }
-
- /**
- * Helper function returning the border width of a specific side.
- *
- * @param variableWidthValue
- * a variable width (could be undefined)
- * @param side
- * the border you want to check
- * @return the variableWidthValue if not undefined, otherwise the borderWidth
- */
- private float getVariableBorderWidth(float variableWidthValue, int side) {
- if ((border & side) != 0)
- return variableWidthValue != UNDEFINED ? variableWidthValue : borderWidth;
- return 0;
- }
-
- /**
- * Helper function updating the border flag for a side based on the specified
- * width. A width of 0 will disable the border on that side. Any other width
- * enables it.
- *
- * @param width
- * width of border
- * @param side
- * border side constant
- */
- private void updateBorderBasedOnWidth(float width, int side) {
- useVariableBorders = true;
- if (width > 0)
- enableBorderSide(side);
- else
- disableBorderSide(side);
- }
-
- /**
- * Gets the width of the left border.
- *
- * @return a width
- */
- public float getBorderWidthLeft() {
- return getVariableBorderWidth(borderWidthLeft, LEFT);
- }
-
- /**
- * Sets the width of the left border.
- *
- * @param borderWidthLeft
- * a width
- */
- public void setBorderWidthLeft(float borderWidthLeft) {
- this.borderWidthLeft = borderWidthLeft;
- updateBorderBasedOnWidth(borderWidthLeft, LEFT);
- }
-
- /**
- * Gets the width of the right border.
- *
- * @return a width
- */
- public float getBorderWidthRight() {
- return getVariableBorderWidth(borderWidthRight, RIGHT);
- }
-
- /**
- * Sets the width of the right border.
- *
- * @param borderWidthRight
- * a width
- */
- public void setBorderWidthRight(float borderWidthRight) {
- this.borderWidthRight = borderWidthRight;
- updateBorderBasedOnWidth(borderWidthRight, RIGHT);
- }
-
- /**
- * Gets the width of the top border.
- *
- * @return a width
- */
- public float getBorderWidthTop() {
- return getVariableBorderWidth(borderWidthTop, TOP);
- }
-
- /**
- * Sets the width of the top border.
- *
- * @param borderWidthTop
- * a width
- */
- public void setBorderWidthTop(float borderWidthTop) {
- this.borderWidthTop = borderWidthTop;
- updateBorderBasedOnWidth(borderWidthTop, TOP);
- }
-
- /**
- * Gets the width of the bottom border.
- *
- * @return a width
- */
- public float getBorderWidthBottom() {
- return getVariableBorderWidth(borderWidthBottom, BOTTOM);
- }
-
- /**
- * Sets the width of the bottom border.
- *
- * @param borderWidthBottom
- * a width
- */
- public void setBorderWidthBottom(float borderWidthBottom) {
- this.borderWidthBottom = borderWidthBottom;
- updateBorderBasedOnWidth(borderWidthBottom, BOTTOM);
- }
-
- // METHODS TO GET/SET THE BORDER COLOR:
-
- /**
- * Gets the color of the border.
- *
- * @return a Color
- */
- public Color getBorderColor() {
- return borderColor;
- }
-
- /**
- * Sets the color of the border.
- *
- * @param borderColor
- * a Color
- */
- public void setBorderColor(Color borderColor) {
- this.borderColor = borderColor;
- }
-
- /**
- * Gets the color of the left border.
- *
- * @return a Color
- */
- public Color getBorderColorLeft() {
- if (borderColorLeft == null)
- return borderColor;
- return borderColorLeft;
- }
-
- /**
- * Sets the color of the left border.
- *
- * @param borderColorLeft
- * a Color
- */
- public void setBorderColorLeft(Color borderColorLeft) {
- this.borderColorLeft = borderColorLeft;
- }
-
- /**
- * Gets the color of the right border.
- *
- * @return a Color
- */
- public Color getBorderColorRight() {
- if (borderColorRight == null)
- return borderColor;
- return borderColorRight;
- }
-
- /**
- * Sets the color of the right border.
- *
- * @param borderColorRight
- * a Color
- */
- public void setBorderColorRight(Color borderColorRight) {
- this.borderColorRight = borderColorRight;
- }
-
- /**
- * Gets the color of the top border.
- *
- * @return a Color
- */
- public Color getBorderColorTop() {
- if (borderColorTop == null)
- return borderColor;
- return borderColorTop;
- }
-
- /**
- * Sets the color of the top border.
- *
- * @param borderColorTop
- * a Color
- */
- public void setBorderColorTop(Color borderColorTop) {
- this.borderColorTop = borderColorTop;
- }
-
- /**
- * Gets the color of the bottom border.
- *
- * @return a Color
- */
- public Color getBorderColorBottom() {
- if (borderColorBottom == null)
- return borderColor;
- return borderColorBottom;
- }
-
- /**
- * Sets the color of the bottom border.
- *
- * @param borderColorBottom
- * a Color
- */
- public void setBorderColorBottom(Color borderColorBottom) {
- this.borderColorBottom = borderColorBottom;
- }
-
- // SPECIAL METHODS:
-
- /**
- * Gets a Rectangle that is altered to fit on the page.
- *
- * @param top
- * the top position
- * @param bottom
- * the bottom position
- * @return a Rectangle
- */
- public Rectangle rectangle(float top, float bottom) {
- Rectangle tmp = new Rectangle(this);
- if (getTop() > top) {
- tmp.setTop(top);
- tmp.disableBorderSide(TOP);
- }
- if (getBottom() < bottom) {
- tmp.setBottom(bottom);
- tmp.disableBorderSide(BOTTOM);
- }
- return tmp;
- }
-
- /**
- * Copies each of the parameters, except the position, from a
- * Rectangle object
- *
- * @param rect
- * Rectangle to copy from
- */
- public void cloneNonPositionParameters(Rectangle rect) {
- this.rotation = rect.rotation;
- this.backgroundColor = rect.backgroundColor;
- this.border = rect.border;
- this.useVariableBorders = rect.useVariableBorders;
- this.borderWidth = rect.borderWidth;
- this.borderWidthLeft = rect.borderWidthLeft;
- this.borderWidthRight = rect.borderWidthRight;
- this.borderWidthTop = rect.borderWidthTop;
- this.borderWidthBottom = rect.borderWidthBottom;
- this.borderColor = rect.borderColor;
- this.borderColorLeft = rect.borderColorLeft;
- this.borderColorRight = rect.borderColorRight;
- this.borderColorTop = rect.borderColorTop;
- this.borderColorBottom = rect.borderColorBottom;
- }
-
- /**
- * Copies each of the parameters, except the position, from a
- * Rectangle object if the value is set there
- *
- * @param rect
- * Rectangle to copy from
- */
- public void softCloneNonPositionParameters(Rectangle rect) {
- if (rect.rotation != 0)
- this.rotation = rect.rotation;
- if (rect.backgroundColor != null)
- this.backgroundColor = rect.backgroundColor;
- if (rect.border != UNDEFINED)
- this.border = rect.border;
- if (useVariableBorders)
- this.useVariableBorders = rect.useVariableBorders;
- if (rect.borderWidth != UNDEFINED)
- this.borderWidth = rect.borderWidth;
- if (rect.borderWidthLeft != UNDEFINED)
- this.borderWidthLeft = rect.borderWidthLeft;
- if (rect.borderWidthRight != UNDEFINED)
- this.borderWidthRight = rect.borderWidthRight;
- if (rect.borderWidthTop != UNDEFINED)
- this.borderWidthTop = rect.borderWidthTop;
- if (rect.borderWidthBottom != UNDEFINED)
- this.borderWidthBottom = rect.borderWidthBottom;
- if (rect.borderColor != null)
- this.borderColor = rect.borderColor;
- if (rect.borderColorLeft != null)
- this.borderColorLeft = rect.borderColorLeft;
- if (rect.borderColorRight != null)
- this.borderColorRight = rect.borderColorRight;
- if (rect.borderColorTop != null)
- this.borderColorTop = rect.borderColorTop;
- if (rect.borderColorBottom != null)
- this.borderColorBottom = rect.borderColorBottom;
- }
-
- /**
- * @return a String representation of the rectangle
- * @see java.lang.Object#toString()
- */
- @Override
- public String toString() {
- StringBuilder buf = new StringBuilder("Rectangle: ");
- buf.append(getWidth());
- buf.append('x');
- buf.append(getHeight());
- buf.append(" (rot: ");
- buf.append(rotation);
- buf.append(" degrees)");
- return buf.toString();
- }
+ /**
+ * Returns the lower left x-coordinate, considering a given margin.
+ *
+ * @param margin
+ * a margin
+ * @return the lower left x-coordinate
+ */
+ public float getLeft(float margin) {
+ return llx + margin;
+ }
+
+ /**
+ * Sets the upper right x-coordinate.
+ *
+ * @param urx
+ * the new value
+ */
+ public void setRight(float urx) {
+ this.urx = urx;
+ }
+
+ /**
+ * Returns the upper right x-coordinate.
+ *
+ * @return the upper right x-coordinate
+ */
+ public float getRight() {
+ return urx;
+ }
+
+ /**
+ * Returns the upper right x-coordinate, considering a given margin.
+ *
+ * @param margin
+ * a margin
+ * @return the upper right x-coordinate
+ */
+ public float getRight(float margin) {
+ return urx - margin;
+ }
+
+ /**
+ * Returns the width of the rectangle.
+ *
+ * @return the width
+ */
+ public float getWidth() {
+ return urx - llx;
+ }
+
+ /**
+ * Sets the upper right y-coordinate.
+ *
+ * @param ury
+ * the new value
+ */
+ public void setTop(float ury) {
+ this.ury = ury;
+ }
+
+ /**
+ * Returns the upper right y-coordinate.
+ *
+ * @return the upper right y-coordinate
+ */
+ public float getTop() {
+ return ury;
+ }
+
+ /**
+ * Returns the upper right y-coordinate, considering a given margin.
+ *
+ * @param margin
+ * a margin
+ * @return the upper right y-coordinate
+ */
+ public float getTop(float margin) {
+ return ury - margin;
+ }
+
+ public float getRelativeTop(){
+ return aFloat;
+ }
+
+ public void setRelativeTop(float relativeTop){
+ this.aFloat = relativeTop;
+ }
+ /**
+ * Sets the lower left y-coordinate.
+ *
+ * @param lly
+ * the new value
+ */
+ public void setBottom(float lly) {
+ this.lly = lly;
+ }
+
+ /**
+ * Returns the lower left y-coordinate.
+ *
+ * @return the lower left y-coordinate
+ */
+ public float getBottom() {
+ return lly;
+ }
+
+ /**
+ * Returns the lower left y-coordinate, considering a given margin.
+ *
+ * @param margin
+ * a margin
+ * @return the lower left y-coordinate
+ */
+ public float getBottom(float margin) {
+ return lly + margin;
+ }
+
+ /**
+ * Returns the height of the rectangle.
+ *
+ * @return the height
+ */
+ public float getHeight() {
+ return ury - lly;
+ }
+
+ /**
+ * Normalizes the rectangle. Switches lower left with upper right if
+ * necessary.
+ */
+ public void normalize() {
+ if (llx > urx) {
+ float a = llx;
+ llx = urx;
+ urx = a;
+ }
+ if (lly > ury) {
+ float a = lly;
+ lly = ury;
+ ury = a;
+ }
+ }
+
+ // METHODS TO GET/SET THE ROTATION:
+
+ /**
+ * Gets the rotation of the rectangle
+ *
+ * @return a rotation value
+ */
+ public int getRotation() {
+ return rotation;
+ }
+
+ /**
+ * Rotates the rectangle. Swaps the values of llx and lly and of urx and ury.
+ *
+ * @return the rotated Rectangle
+ */
+ public Rectangle rotate() {
+ Rectangle rect = new Rectangle(lly, llx, ury, urx);
+ rect.rotation = rotation + 90;
+ rect.rotation %= 360;
+ return rect;
+ }
+
+ // METHODS TO GET/SET THE BACKGROUND COLOR:
+
+ /**
+ * Gets the backgroundcolor.
+ *
+ * @return a Color
+ */
+ public Color getBackgroundColor() {
+ return backgroundColor;
+ }
+
+ /**
+ * Sets the backgroundcolor of the rectangle.
+ *
+ * @param backgroundColor
+ * a Color
+ */
+
+ public void setBackgroundColor(Color backgroundColor) {
+ this.backgroundColor = backgroundColor;
+ }
+
+ /**
+ * Gets the grayscale.
+ *
+ * @return the grayscale color of the background or 0 if the background has no
+ * grayscale color.
+ */
+ public float getGrayFill() {
+ if (backgroundColor instanceof GrayColor)
+ return ((GrayColor) backgroundColor).getGray();
+ return 0;
+ }
+
+ /**
+ * Sets the the background color to a grayscale value.
+ *
+ * @param value
+ * the new grayscale value
+ */
+ public void setGrayFill(float value) {
+ backgroundColor = new GrayColor(value);
+ }
+
+ // METHODS TO GET/SET THE BORDER:
+
+ /**
+ * Returns the exact type of the border.
+ *
+ * @return a value
+ */
+ public int getBorder() {
+ return border;
+ }
+
+ /**
+ * Indicates whether some type of border is set.
+ *
+ * @return a boolean
+ */
+ public boolean hasBorders() {
+ switch (border) {
+ case UNDEFINED:
+ case NO_BORDER:
+ return false;
+ default:
+ return borderWidth > 0 || borderWidthLeft > 0 || borderWidthRight > 0
+ || borderWidthTop > 0 || borderWidthBottom > 0;
+ }
+ }
+
+ /**
+ * Indicates whether the specified type of border is set.
+ *
+ * @param type
+ * the type of border
+ * @return a boolean
+ */
+ public boolean hasBorder(int type) {
+ if (border == UNDEFINED)
+ return false;
+ return (border & type) == type;
+ }
+
+ /**
+ * Enables/Disables the border on the specified sides. The border is specified
+ * as an integer bitwise combination of the constants:
+ * LEFT, RIGHT, TOP, BOTTOM.
+ *
+ * @see #enableBorderSide(int)
+ * @see #disableBorderSide(int)
+ * @param border
+ * the new value
+ */
+ public void setBorder(int border) {
+ this.border = border;
+ }
+
+ /**
+ * Indicates whether variable width borders are being used. Returns true if
+ * setBorderWidthLeft, setBorderWidthRight,
+ * setBorderWidthTop, or setBorderWidthBottom has been called.
+ *
+ * @return true if variable width borders are in use
+ */
+ public boolean isUseVariableBorders() {
+ return useVariableBorders;
+ }
+
+ /**
+ * Sets a parameter indicating if the rectangle has variable borders
+ *
+ * @param useVariableBorders
+ * indication if the rectangle has variable borders
+ */
+ public void setUseVariableBorders(boolean useVariableBorders) {
+ this.useVariableBorders = useVariableBorders;
+ }
+
+ /**
+ * Enables the border on the specified side.
+ *
+ * @param side
+ * the side to enable. One of LEFT, RIGHT, TOP, BOTTOM
+ */
+ public void enableBorderSide(int side) {
+ if (border == UNDEFINED)
+ border = 0;
+ border |= side;
+ }
+
+ /**
+ * Disables the border on the specified side.
+ *
+ * @param side
+ * the side to disable. One of LEFT, RIGHT, TOP, BOTTOM
+ */
+ public void disableBorderSide(int side) {
+ if (border == UNDEFINED)
+ border = 0;
+ border &= ~side;
+ }
+
+ // METHODS TO GET/SET THE BORDER WIDTH:
+
+ /**
+ * Gets the borderwidth.
+ *
+ * @return a value
+ */
+ public float getBorderWidth() {
+ return borderWidth;
+ }
+
+ /**
+ * Sets the borderwidth of the table.
+ *
+ * @param borderWidth
+ * the new value
+ */
+ public void setBorderWidth(float borderWidth) {
+ this.borderWidth = borderWidth;
+ }
+
+ /**
+ * Helper function returning the border width of a specific side.
+ *
+ * @param variableWidthValue
+ * a variable width (could be undefined)
+ * @param side
+ * the border you want to check
+ * @return the variableWidthValue if not undefined, otherwise the borderWidth
+ */
+ private float getVariableBorderWidth(float variableWidthValue, int side) {
+ if ((border & side) != 0)
+ return variableWidthValue != UNDEFINED ? variableWidthValue : borderWidth;
+ return 0;
+ }
+
+ /**
+ * Helper function updating the border flag for a side based on the specified
+ * width. A width of 0 will disable the border on that side. Any other width
+ * enables it.
+ *
+ * @param width
+ * width of border
+ * @param side
+ * border side constant
+ */
+ private void updateBorderBasedOnWidth(float width, int side) {
+ useVariableBorders = true;
+ if (width > 0)
+ enableBorderSide(side);
+ else
+ disableBorderSide(side);
+ }
+
+ /**
+ * Gets the width of the left border.
+ *
+ * @return a width
+ */
+ public float getBorderWidthLeft() {
+ return getVariableBorderWidth(borderWidthLeft, LEFT);
+ }
+
+ /**
+ * Sets the width of the left border.
+ *
+ * @param borderWidthLeft
+ * a width
+ */
+ public void setBorderWidthLeft(float borderWidthLeft) {
+ this.borderWidthLeft = borderWidthLeft;
+ updateBorderBasedOnWidth(borderWidthLeft, LEFT);
+ }
+
+ /**
+ * Gets the width of the right border.
+ *
+ * @return a width
+ */
+ public float getBorderWidthRight() {
+ return getVariableBorderWidth(borderWidthRight, RIGHT);
+ }
+
+ /**
+ * Sets the width of the right border.
+ *
+ * @param borderWidthRight
+ * a width
+ */
+ public void setBorderWidthRight(float borderWidthRight) {
+ this.borderWidthRight = borderWidthRight;
+ updateBorderBasedOnWidth(borderWidthRight, RIGHT);
+ }
+
+ /**
+ * Gets the width of the top border.
+ *
+ * @return a width
+ */
+ public float getBorderWidthTop() {
+ return getVariableBorderWidth(borderWidthTop, TOP);
+ }
+
+ /**
+ * Sets the width of the top border.
+ *
+ * @param borderWidthTop
+ * a width
+ */
+ public void setBorderWidthTop(float borderWidthTop) {
+ this.borderWidthTop = borderWidthTop;
+ updateBorderBasedOnWidth(borderWidthTop, TOP);
+ }
+
+ /**
+ * Gets the width of the bottom border.
+ *
+ * @return a width
+ */
+ public float getBorderWidthBottom() {
+ return getVariableBorderWidth(borderWidthBottom, BOTTOM);
+ }
+
+ /**
+ * Sets the width of the bottom border.
+ *
+ * @param borderWidthBottom
+ * a width
+ */
+ public void setBorderWidthBottom(float borderWidthBottom) {
+ this.borderWidthBottom = borderWidthBottom;
+ updateBorderBasedOnWidth(borderWidthBottom, BOTTOM);
+ }
+
+ // METHODS TO GET/SET THE BORDER COLOR:
+
+ /**
+ * Gets the color of the border.
+ *
+ * @return a Color
+ */
+ public Color getBorderColor() {
+ return borderColor;
+ }
+
+ /**
+ * Sets the color of the border.
+ *
+ * @param borderColor
+ * a Color
+ */
+ public void setBorderColor(Color borderColor) {
+ this.borderColor = borderColor;
+ }
+
+ /**
+ * Gets the color of the left border.
+ *
+ * @return a Color
+ */
+ public Color getBorderColorLeft() {
+ if (borderColorLeft == null)
+ return borderColor;
+ return borderColorLeft;
+ }
+
+ /**
+ * Sets the color of the left border.
+ *
+ * @param borderColorLeft
+ * a Color
+ */
+ public void setBorderColorLeft(Color borderColorLeft) {
+ this.borderColorLeft = borderColorLeft;
+ }
+
+ /**
+ * Gets the color of the right border.
+ *
+ * @return a Color
+ */
+ public Color getBorderColorRight() {
+ if (borderColorRight == null)
+ return borderColor;
+ return borderColorRight;
+ }
+
+ /**
+ * Sets the color of the right border.
+ *
+ * @param borderColorRight
+ * a Color
+ */
+ public void setBorderColorRight(Color borderColorRight) {
+ this.borderColorRight = borderColorRight;
+ }
+
+ /**
+ * Gets the color of the top border.
+ *
+ * @return a Color
+ */
+ public Color getBorderColorTop() {
+ if (borderColorTop == null)
+ return borderColor;
+ return borderColorTop;
+ }
+
+ /**
+ * Sets the color of the top border.
+ *
+ * @param borderColorTop
+ * a Color
+ */
+ public void setBorderColorTop(Color borderColorTop) {
+ this.borderColorTop = borderColorTop;
+ }
+
+ /**
+ * Gets the color of the bottom border.
+ *
+ * @return a Color
+ */
+ public Color getBorderColorBottom() {
+ if (borderColorBottom == null)
+ return borderColor;
+ return borderColorBottom;
+ }
+
+ /**
+ * Sets the color of the bottom border.
+ *
+ * @param borderColorBottom
+ * a Color
+ */
+ public void setBorderColorBottom(Color borderColorBottom) {
+ this.borderColorBottom = borderColorBottom;
+ }
+
+ // SPECIAL METHODS:
+
+ /**
+ * Gets a Rectangle that is altered to fit on the page.
+ *
+ * @param top
+ * the top position
+ * @param bottom
+ * the bottom position
+ * @return a Rectangle
+ */
+ public Rectangle rectangle(float top, float bottom) {
+ Rectangle tmp = new Rectangle(this);
+ if (getTop() > top) {
+ tmp.setTop(top);
+ tmp.disableBorderSide(TOP);
+ }
+ if (getBottom() < bottom) {
+ tmp.setBottom(bottom);
+ tmp.disableBorderSide(BOTTOM);
+ }
+ return tmp;
+ }
+
+ /**
+ * Copies each of the parameters, except the position, from a
+ * Rectangle object
+ *
+ * @param rect
+ * Rectangle to copy from
+ */
+ public void cloneNonPositionParameters(Rectangle rect) {
+ this.rotation = rect.rotation;
+ this.backgroundColor = rect.backgroundColor;
+ this.border = rect.border;
+ this.useVariableBorders = rect.useVariableBorders;
+ this.borderWidth = rect.borderWidth;
+ this.borderWidthLeft = rect.borderWidthLeft;
+ this.borderWidthRight = rect.borderWidthRight;
+ this.borderWidthTop = rect.borderWidthTop;
+ this.borderWidthBottom = rect.borderWidthBottom;
+ this.borderColor = rect.borderColor;
+ this.borderColorLeft = rect.borderColorLeft;
+ this.borderColorRight = rect.borderColorRight;
+ this.borderColorTop = rect.borderColorTop;
+ this.borderColorBottom = rect.borderColorBottom;
+ }
+
+ /**
+ * Copies each of the parameters, except the position, from a
+ * Rectangle object if the value is set there
+ *
+ * @param rect
+ * Rectangle to copy from
+ */
+ public void softCloneNonPositionParameters(Rectangle rect) {
+ if (rect.rotation != 0)
+ this.rotation = rect.rotation;
+ if (rect.backgroundColor != null)
+ this.backgroundColor = rect.backgroundColor;
+ if (rect.border != UNDEFINED)
+ this.border = rect.border;
+ if (useVariableBorders)
+ this.useVariableBorders = rect.useVariableBorders;
+ if (rect.borderWidth != UNDEFINED)
+ this.borderWidth = rect.borderWidth;
+ if (rect.borderWidthLeft != UNDEFINED)
+ this.borderWidthLeft = rect.borderWidthLeft;
+ if (rect.borderWidthRight != UNDEFINED)
+ this.borderWidthRight = rect.borderWidthRight;
+ if (rect.borderWidthTop != UNDEFINED)
+ this.borderWidthTop = rect.borderWidthTop;
+ if (rect.borderWidthBottom != UNDEFINED)
+ this.borderWidthBottom = rect.borderWidthBottom;
+ if (rect.borderColor != null)
+ this.borderColor = rect.borderColor;
+ if (rect.borderColorLeft != null)
+ this.borderColorLeft = rect.borderColorLeft;
+ if (rect.borderColorRight != null)
+ this.borderColorRight = rect.borderColorRight;
+ if (rect.borderColorTop != null)
+ this.borderColorTop = rect.borderColorTop;
+ if (rect.borderColorBottom != null)
+ this.borderColorBottom = rect.borderColorBottom;
+ }
+
+ /**
+ * @return a String representation of the rectangle
+ * @see java.lang.Object#toString()
+ */
+ @Override
+ public String toString() {
+ StringBuilder buf = new StringBuilder("Rectangle: ");
+ buf.append(getWidth());
+ buf.append('x');
+ buf.append(getHeight());
+ buf.append(" (rot: ");
+ buf.append(rotation);
+ buf.append(" degrees)");
+ return buf.toString();
+ }
}
\ No newline at end of file
diff --git a/openpdf/src/main/java/com/lowagie/text/pdf/PdfDocument.java b/openpdf/src/main/java/com/lowagie/text/pdf/PdfDocument.java
index b3274956f..f320b2117 100644
--- a/openpdf/src/main/java/com/lowagie/text/pdf/PdfDocument.java
+++ b/openpdf/src/main/java/com/lowagie/text/pdf/PdfDocument.java
@@ -567,7 +567,7 @@ public boolean add(Element element) throws DocumentException {
PdfPageEvent pageEvent = writer.getPageEvent();
boolean hasTitle = section.isNotAddedYet()
- && section.getTitle() != null;
+ && section.getTitle() != null;
// if the section is a chapter, we begin a new page
if (section.isTriggerNewPage()) {
@@ -676,17 +676,22 @@ public boolean add(Element element) throws DocumentException {
break;
}
case Element.PTABLE: {
- PdfPTable ptable = (PdfPTable)element;
+ PdfPTable ptable = (PdfPTable) element;
if (ptable.size() <= ptable.getHeaderRows())
break; //nothing to do
- // before every table, we add a new line and flush all lines
- ensureNewLine();
- flushLines();
+ if(isDoFooter) {
+ delayTableAddition(ptable);
+ } else {
+ // before every table, we add a new line and flush all lines
+ ensureNewLine();
+ flushLines();
+
+ addPTable(ptable);
+ pageEmpty = false;
+ newLine();
+ }
- addPTable(ptable);
- pageEmpty = false;
- newLine();
break;
}
case Element.MULTI_COLUMN_TEXT: {
@@ -713,15 +718,15 @@ public boolean add(Element element) throws DocumentException {
break;
} else if (element instanceof Table) {
try {
- PdfPTable ptable = ((Table)element).createPdfPTable();
- if (ptable.size() <= ptable.getHeaderRows())
- break; //nothing to do
- // before every table, we add a new line and flush all lines
- ensureNewLine();
- flushLines();
- addPTable(ptable);
- pageEmpty = false;
- break;
+ PdfPTable ptable = ((Table)element).createPdfPTable();
+ if (ptable.size() <= ptable.getHeaderRows())
+ break; //nothing to do
+ // before every table, we add a new line and flush all lines
+ ensureNewLine();
+ flushLines();
+ addPTable(ptable);
+ pageEmpty = false;
+ break;
}
catch(BadElementException bee) {
// constructing the PdfTable
@@ -745,7 +750,12 @@ public boolean add(Element element) throws DocumentException {
case Element.IMGRAW:
case Element.IMGTEMPLATE: {
//carriageReturn(); suggestion by Marc Campforts
- add((Image) element);
+ if(isDoFooter){
+ addDelay((Image) element);
+ }else{
+ add((Image) element);
+ }
+
break;
}
case Element.YMARK: {
@@ -777,37 +787,45 @@ public boolean add(Element element) throws DocumentException {
}
}
+
+ /**
+ * Integrate a paragraph into a table, so it can be a whole.
+ * Note: This is not a table with square, it's just like the paragraph, but
+ * it cannot be separated.
+ * @param paragraph the {@code Paragraph} incoming paragraphs to be consolidated
+ * @return {@code PdfPTable} the whole which will be used later
+ */
static PdfPTable createInOneCell(Paragraph paragraph) {
PdfPTable table = new PdfPTable(1);
table.setWidthPercentage(100f);
-
PdfPCell cell = new PdfPCell();
cell.setBorder(Table.NO_BORDER);
cell.setPadding(0);
-
- for (int i=0; iElement into document
+ */
+
+ protected void flushSpecial() {
+ if(footer.getSpecialContent() == null){
+ return;
+ }
+ for (Element element : footer.getSpecialContent()) {
+ switch (element.type()) {
+ case Element.JPEG:
+ case Element.JPEG2000:
+ case Element.JBIG2:
+ case Element.IMGRAW:
+ case Element.IMGTEMPLATE: {
+ Image image = (Image) element;
+ boolean textwrap = (image.getAlignment() & Image.TEXTWRAP) == Image.TEXTWRAP
+ && !((image.getAlignment() & Image.MIDDLE) == Image.MIDDLE);
+ float diff = leading / 2;
+ if (textwrap) {
+ diff += leading;
+ }
+ float lowerleft = footer.getTop() - image.getRelativeTop() - image.getScaledHeight() - diff;
+
+ float[] matrix = image.matrix();
+ float startPosition = indentLeft() - matrix[4];
+ if ((image.getAlignment() & Image.RIGHT) == Image.RIGHT)
+ startPosition = indentRight() - image.getScaledWidth() - matrix[4];
+ if ((image.getAlignment() & Image.MIDDLE) == Image.MIDDLE)
+ startPosition = indentLeft() + ((indentRight() - indentLeft() - image.getScaledWidth()) / 2) - matrix[4];
+ if (image.hasAbsoluteX()) startPosition = image.getAbsoluteX();
+
+ if (!textwrap) {
+ if ((image.getAlignment() & Image.RIGHT) == Image.RIGHT)
+ startPosition -= image.getIndentationRight();
+ else if ((image.getAlignment() & Image.MIDDLE) == Image.MIDDLE)
+ startPosition += image.getIndentationLeft() - image.getIndentationRight();
+ else startPosition += image.getIndentationLeft();
+ }
+ graphics.addImage(image, matrix[0], matrix[1], matrix[2], matrix[3], startPosition, lowerleft - matrix[5]);
+ break;
+ }
+ case Element.PTABLE:
+ PdfPTable pdfPTable = (PdfPTable) element;
+
+ ColumnText columnText = new ColumnText(writer.getDirectContent());
+ columnText.addElement(pdfPTable);
+
+ columnText.setSimpleColumn(indentLeft(), footer.getBottom(), indentRight(), footer.getTop());
+ columnText.go();
+
+ break;
+ }
+ }
+ footer.setPadding(0);
+ }
+
+ /**
+ * Occupies space for Image that will be added later instead of now
+ *
+ * @param image the new Image
+ */
+
+ protected void addDelay(Image image) {
+ if (image.hasAbsoluteY()) {
+ System.out.println("Warning: absoluteY of image is invalid in footer");
+ }
+
+ image.setRelativeTop(currentHeight); // set the offset relative to the top
+ image.setAlignment(image.getAlignment() | footer.alignment());
+ footer.addSpecialContent(image);
+
+ // add indentation for text
+ boolean textwrap = (image.getAlignment() & Image.TEXTWRAP) == Image.TEXTWRAP
+ && !((image.getAlignment() & Image.MIDDLE) == Image.MIDDLE);
+ boolean underlying = (image.getAlignment() & Image.UNDERLYING) == Image.UNDERLYING;
+ float diff = leading / 2;
+ if (textwrap) {
+ if (imageEnd < 0 || imageEnd < currentHeight + image.getScaledHeight() + diff) {
+ imageEnd = currentHeight + image.getScaledHeight() + diff;
+ }
+ if ((image.getAlignment() & Image.RIGHT) == Image.RIGHT) {
+ // indentation suggested by Pelikan Stephan
+ indentation.imageIndentRight += image.getScaledWidth() + image.getIndentationLeft();
+ } else {
+ // indentation suggested by Pelikan Stephan
+ indentation.imageIndentLeft += image.getScaledWidth() + image.getIndentationRight();
+ }
+ }
+ // move text
+ if (!(textwrap || underlying)) {
+ currentHeight += image.getScaledHeight() + diff;
+ flushLines();
+ text.moveText(0, -(image.getScaledHeight() + diff));
+ newLine();
+ } else {
+ footer.addPadding(image.getScaledHeight() + diff);
+ }
+ }
+
+ /**
+ * Occupies space for PdfPTable that will be added later instead of now
+ *
+ * @param table the new PdfPTable
+ */
+ protected void delayTableAddition(PdfPTable table) {
+ setTableWidth(table);
+ final float footerPadding = table.getTotalHeight() - (0.75f * leading);
+
+ footer.addSpecialContent(table);
+ footer.addPadding(footerPadding);
+ }
+
+ // [M4] Adding a PdfPTable
/** Adds a PdfPTable to the document.
* @param ptable the PdfPTable to be added to the document.
@@ -2580,14 +2711,18 @@ void addPTable(PdfPTable ptable) throws DocumentException {
*/
boolean fitsPage(PdfPTable table, float margin) {
+ setTableWidth(table);
+ // ensuring that a new line has been started.
+ ensureNewLine();
+ return table.getTotalHeight() + ((currentHeight > 0) ? table.spacingBefore() : 0f)
+ <= indentTop() - currentHeight - indentBottom() - margin;
+ }
+
+ private void setTableWidth(final PdfPTable table) {
if (!table.isLockedWidth()) {
float totalWidth = (indentRight() - indentLeft()) * table.getWidthPercentage() / 100;
table.setTotalWidth(totalWidth);
}
- // ensuring that a new line has been started.
- ensureNewLine();
- return table.getTotalHeight() + ((currentHeight > 0) ? table.spacingBefore() : 0f)
- <= indentTop() - currentHeight - indentBottom() - margin;
}
// [M4'] Adding a Table
@@ -3072,7 +3207,7 @@ protected void renderCells(RenderingContext ctx, java.util.List cells, boolean h
// we paint the borders of the cells
Rectangle cellRect = cell.rectangle(tableRect.getTop(), indentBottom);
- //cellRect.setBottom(cellRect.bottom());
+ //cellRect.setBottom(cellRect.bottom());
if (cellRect.getHeight() > 0) {
ctx.lostTableBottom = indentBottom;
ctx.cellGraphics.rectangle(cellRect);
@@ -3102,8 +3237,12 @@ float bottom(Table table) {
}
// [M5] header/footer
+ /** This is the flag meaning whether document is creating footer. */
+ private boolean isDoFooter = false;
+
protected void doFooter() throws DocumentException {
if (footer == null) return;
+ isDoFooter = true;
// Begin added by Edgar Leonardo Prieto Perilla
// Avoid footer indentation
float tmpIndentLeft = indentation.indentLeft;
@@ -3129,11 +3268,12 @@ protected void doFooter() throws DocumentException {
text.moveText(left(), indentBottom());
flushLines();
text.moveText(-left(), -bottom());
- footer.setTop(bottom(currentHeight));
+ footer.setTop(bottom(Math.max(footer.getPadding(), currentHeight)));
footer.setBottom(bottom() - (0.75f * leading));
footer.setLeft(left());
footer.setRight(right());
graphics.rectangle(footer);
+ flushSpecial();
indentation.indentBottom = currentHeight + leading * 2;
currentHeight = 0;
// Begin added by Edgar Leonardo Prieto Perilla
@@ -3145,6 +3285,7 @@ protected void doFooter() throws DocumentException {
indentation.imageIndentRight = tmpImageIndentRight;
// End added: Bonf (Marc Schneider) 2003-07-29
// End added by Edgar Leonardo Prieto Perilla
+ isDoFooter = false;
}
protected void doHeader() throws DocumentException {
@@ -3190,4 +3331,4 @@ protected void doHeader() throws DocumentException {
// End added: Bonf (Marc Schneider) 2003-07-29
// End Added by Edgar Leonardo Prieto Perilla
}
-}
+}
\ No newline at end of file
diff --git a/openpdf/src/test/java/com/lowagie/text/FooterTableTest.java b/openpdf/src/test/java/com/lowagie/text/FooterTableTest.java
new file mode 100644
index 000000000..06278212f
--- /dev/null
+++ b/openpdf/src/test/java/com/lowagie/text/FooterTableTest.java
@@ -0,0 +1,62 @@
+package com.lowagie.text;
+
+import java.io.FileOutputStream;
+import java.io.IOException;
+import java.util.Objects;
+
+import org.junit.jupiter.api.Assertions;
+import org.junit.jupiter.api.Test;
+
+import com.lowagie.text.pdf.PdfPTable;
+import com.lowagie.text.pdf.PdfWriter;
+
+public class FooterTableTest {
+ @Test
+ public void imageLeftAlignmentPositionTest() throws IOException {
+ Document document = new Document(PageSize.A4);
+ PdfWriter.getInstance(document, new FileOutputStream("footer-table-test.pdf"));
+
+ Image jpg = Image.getInstance(Objects.requireNonNull(getClass().getClassLoader().getResource("GitHub-Mark-32px.png")));
+ jpg.setAlignment(Image.RIGHT);
+
+ PdfPTable table = new PdfPTable(3);
+ table.getDefaultCell().setBorder(Table.NO_BORDER);
+ table.addCell("1.1");
+ table.addCell("1.2");
+ table.addCell("1.3");
+ table.addCell("2.1");
+ table.addCell(new Phrase("center"));
+ table.addCell("2.3");
+ table.addCell("3.1");
+ table.addCell("3.2");
+ table.addCell("3.3");
+
+ Paragraph footerParagraph = new Paragraph();
+ footerParagraph.add(jpg);
+ footerParagraph.add(table);
+
+ HeaderFooter footer = new HeaderFooter(footerParagraph, false);
+ document.setFooter(footer);
+
+ document.open();
+ document.add(new Paragraph("This is fixed smellbusters test."));
+ document.add(new Paragraph("Jon line"));
+ document.newPage();
+ document.add(new Paragraph("second"));
+ document.newPage();
+ document.add(new Paragraph("third"));
+ document.close();
+
+ float tableHeight = table.getTotalHeight();
+ float footerTop = footer.getTop();
+ float tableBottom = footerTop - table.getTotalHeight();
+ Assertions.assertEquals(48.0, tableHeight);
+ Assertions.assertEquals(76.0, footerTop);
+ Assertions.assertEquals(28.0, tableBottom);
+ }
+
+ public static void main(String[] args) throws IOException {
+ FooterTableTest test = new FooterTableTest();
+ test.imageLeftAlignmentPositionTest();
+ }
+}
\ No newline at end of file
diff --git a/openpdf/src/test/java/com/lowagie/text/pdf/FooterImageTest.java b/openpdf/src/test/java/com/lowagie/text/pdf/FooterImageTest.java
new file mode 100644
index 000000000..faa0b5bda
--- /dev/null
+++ b/openpdf/src/test/java/com/lowagie/text/pdf/FooterImageTest.java
@@ -0,0 +1,158 @@
+package com.lowagie.text.pdf;
+
+import com.lowagie.text.*;
+import org.junit.jupiter.api.Assertions;
+import org.junit.jupiter.api.Test;
+
+import java.io.FileOutputStream;
+import java.io.IOException;
+import java.util.Objects;
+
+class FooterImageTest {
+ @Test
+ void onlyTextFooterUpperBoundTest() throws IOException {
+ Document document = new Document(PageSize.A4);
+ PdfWriter.getInstance(document, new FileOutputStream("footer-only-text.pdf"));
+
+ Paragraph footerParagraph = new Paragraph();
+ String test = "This is a smellbusters test.";
+ String footerstr = "footer";
+ footerParagraph.add(footerstr);
+ HeaderFooter footer = new HeaderFooter(footerParagraph, false);
+ document.setFooter(footer);
+
+ document.open();
+ document.add(new Paragraph(test));
+ document.close();
+ Assertions.assertEquals(52.0, footer.getTop());
+ }
+
+ @Test
+ void imageLeftAlignmentPositionTest() throws IOException {
+ Document document = new Document(PageSize.A4);
+ Image jpg = Image.getInstance(Objects.requireNonNull(getClass().getClassLoader().getResource("GitHub-Mark-32px.png")));
+ PdfWriter.getInstance(document, new FileOutputStream("footer-image-left.pdf"));
+
+ Paragraph footerParagraph = new Paragraph();
+ String test = "This is a smellbusters line.";
+ String footerstr = "footer";
+ footerParagraph.add(jpg);
+ footerParagraph.add(footerstr);
+ HeaderFooter footer = new HeaderFooter(footerParagraph, false);
+ document.setFooter(footer);
+
+ document.open();
+ document.add(new Paragraph(test));
+ document.close();
+
+ float footerTop = footer.getTop();
+ float imageBottom = footerTop - jpg.getRelativeTop() - jpg.getScaledHeight();
+ float imageIndentLeft = document.left() - jpg.matrix()[4];
+ Assertions.assertEquals(92.0, footerTop);
+ Assertions.assertEquals(60.0, imageBottom);
+ Assertions.assertEquals(36.0, imageIndentLeft);
+ }
+
+ @Test
+ void imageRightAlignmentPositionTest() throws IOException {
+ Document document = new Document(PageSize.A4);
+ Image jpg = Image.getInstance(Objects.requireNonNull(getClass().getClassLoader().getResource("GitHub-Mark-32px.png")));
+ PdfWriter.getInstance(document, new FileOutputStream("footer-image-right.pdf"));
+ jpg.setAlignment(Element.ALIGN_RIGHT);
+
+ Paragraph footerParagraph = new Paragraph();
+ String test = "This is a smellbusters line.";
+ footerParagraph.add(jpg);
+ HeaderFooter footer = new HeaderFooter(footerParagraph, false);
+ document.setFooter(footer);
+
+ document.open();
+ document.add(new Paragraph(test));
+ document.close();
+
+ float footerTop = footer.getTop();
+ float imageBottom = footerTop - jpg.getRelativeTop() - jpg.getScaledHeight();
+ float imageIndentRight = document.right() - jpg.getScaledWidth() - jpg.matrix()[4];
+ imageIndentRight -= jpg.getIndentationRight();
+ Assertions.assertEquals(76.0, footerTop);
+ Assertions.assertEquals(44.0, imageBottom);
+ Assertions.assertEquals(527.0, imageIndentRight);
+ }
+
+ @Test
+ void centerUnderlyingPositionTest() throws IOException {
+ Document document = new Document(PageSize.A4);
+ Image jpg = Image.getInstance(Objects.requireNonNull(getClass().getClassLoader().getResource("GitHub-Mark-32px.png")));
+ jpg.setAlignment(Image.UNDERLYING);
+
+ PdfWriter.getInstance(document, new FileOutputStream("footer-image-center.pdf"));
+
+ Paragraph footerParagraph = new Paragraph();
+ String test = "This is a test smellbusters.";
+ footerParagraph.add(jpg);
+ HeaderFooter footer = new HeaderFooter(footerParagraph, true);
+ footer.setAlignment(Element.ALIGN_CENTER);
+ document.setFooter(footer);
+
+ document.open();
+ document.add(new Paragraph(test));
+ document.close();
+
+ float footerTop = footer.getTop();
+ float imageBottom = footerTop - jpg.getRelativeTop() - jpg.getScaledHeight();
+ float imageIndentLeft = document.left() + (document.right() - document.left() - jpg.getScaledWidth()) / 2;
+ imageIndentLeft -= jpg.getIndentationRight() + jpg.matrix()[4];
+ Assertions.assertEquals(76.0, footerTop);
+ Assertions.assertEquals(44.0, imageBottom);
+ Assertions.assertEquals(281.5, imageIndentLeft);
+ }
+
+ @Test
+ void multiplePageWithImageAndNumberTest() throws IOException {
+ Document document = new Document(PageSize.A4);
+ Image jpg = Image.getInstance(Objects.requireNonNull(getClass().getClassLoader().getResource("GitHub-Mark-32px.png")));
+ jpg.setAlignment(Image.UNDERLYING);
+
+ PdfWriter.getInstance(document, new FileOutputStream("footer-image-multiple-pages.pdf"));
+
+ Paragraph footerParagraph = new Paragraph();
+ String test = "Smellbusters manual.";
+ footerParagraph.add(jpg);
+ HeaderFooter footer = new HeaderFooter(footerParagraph, true);
+ footer.setAlignment(Element.ALIGN_CENTER);
+ document.setFooter(footer);
+
+ document.open();
+ for (int i = 0; i < 100; i++) {
+ document.add(new Paragraph(test));
+ }
+ document.close();
+
+ float footerTop = footer.getTop();
+ float imageBottom = footerTop - jpg.getRelativeTop() - jpg.getScaledHeight();
+ float imageIndentLeft = document.left() + (document.right() - document.left() - jpg.getScaledWidth()) / 2;
+ imageIndentLeft -= jpg.getIndentationRight() + jpg.matrix()[4];
+ Assertions.assertEquals(76.0, footerTop);
+ Assertions.assertEquals(44.0, imageBottom);
+ Assertions.assertEquals(281.5, imageIndentLeft);
+
+ }
+
+ public static void main(String[] args) throws IOException {
+ FooterImageTest test = new FooterImageTest();
+
+
+ test.onlyTextFooterUpperBoundTest();
+
+
+ test.imageLeftAlignmentPositionTest();
+
+ test.imageRightAlignmentPositionTest();
+
+
+ test.centerUnderlyingPositionTest();
+
+ test.multiplePageWithImageAndNumberTest();
+
+ }
+}
\ No newline at end of file
diff --git a/openpdf/src/test/resources/GitHub-Mark-32px.png b/openpdf/src/test/resources/GitHub-Mark-32px.png
new file mode 100644
index 000000000..8b25551a9
Binary files /dev/null and b/openpdf/src/test/resources/GitHub-Mark-32px.png differ
diff --git a/pom.xml b/pom.xml
index 1f7bea9ad..90cf5ebbd 100644
--- a/pom.xml
+++ b/pom.xml
@@ -308,20 +308,6 @@