All Downloads are FREE. Search and download functionalities are using the official Maven repository.

de.intarsys.pdf.cds.CDSRectangle Maven / Gradle / Ivy

/*
 * Copyright (c) 2007, intarsys consulting GmbH
 *
 * Redistribution and use in source and binary forms, with or without
 * modification, are permitted provided that the following conditions are met:
 *
 * - Redistributions of source code must retain the above copyright notice,
 *   this list of conditions and the following disclaimer.
 *
 * - Redistributions in binary form must reproduce the above copyright notice,
 *   this list of conditions and the following disclaimer in the documentation
 *   and/or other materials provided with the distribution.
 *
 * - Neither the name of intarsys nor the names of its contributors may be used
 *   to endorse or promote products derived from this software without specific
 *   prior written permission.
 *
 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
 * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
 * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
 * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
 * POSSIBILITY OF SUCH DAMAGE.
 */
package de.intarsys.pdf.cds;

import java.awt.geom.Rectangle2D;

import de.intarsys.pdf.cos.COSArray;
import de.intarsys.pdf.cos.COSFixed;
import de.intarsys.pdf.cos.COSNumber;

/**
 * The implementation of the pdf rectangle data type.
 * 
 * 

* The specification of the data type is found in [PDF} chapter 3.8.3. *

* *

* *

 *              A rectangle is defined by
 *                   [llx, lly, urx, ury ]
 *              where
 *                   llx = lower left x coordinate
 *                   lly = lower left y coordinate
 *                   urx = upper right x coordinate
 *                   ury = upper right y coordinate
 * 
 *                          urx
 *                           |
 *                           v
 *                     +-----+  <-ury
 *                     |     |
 *              lly -> +-----+
 *                     ˆ
 *                     |
 *                    llx
 * 
 * 
 * 
* * An application should be prepared to get any two diagonally opposite corners * in the rectangle specification. Use "normalize()" to ensure a rectangle that * conforms to the above picture. *

*/ public class CDSRectangle extends CDSBase { /** Some common constants in rectangle */ static private final float INCH_2_CM = 2.54f; static private final float A4_WIDTH = 21.0f; static private final float A4_HEIGHT = 29.7f; static private final float DPI = 72.0f; /* * paper sizes in mm A0 841 ? 1189 B0 1000 ? 1414 C0 17 ? 1297 A1 594 ? 841 * B1 707 ? 1000 C1 648 ? 917 A2 420 ? 594 B2 500 ? 707 C2 458 ? 648 A3 297 ? * 420 B3 353 ? 500 C3 324 ? 458 A4 210 ? 297 B4 250 ? 353 C4 229 ? 324 A5 * 148 ? 210 B5 176 ? 250 C5 162 ? 229 A6 105 ? 148 B6 125 ? 176 C6 114 ? * 162 A7 74 ? 105 B7 88 ? 125 C7 81 ? 114 A8 52 ? 74 B8 62 ? 88 C8 57 ? 81 * A9 37 ? 52 B9 44 ? 62 C9 40 ? 57 A10 26 ? 37 B10 31 ? 44 C10 28 ? 40 */ // todo 4 add some common paper sizes static public final float[] SIZE_A4 = { 0, 0, (A4_WIDTH / INCH_2_CM * DPI), (A4_HEIGHT / INCH_2_CM * DPI) }; /** * Create a {@link CDSRectangle} from an array holding the * rectangle coordinates. * * @param array * The base {@link COSArray} * * @return Create a {@link CDSRectangle} from array */ static public CDSRectangle createFromCOS(COSArray array) { if (array == null) { return null; } CDSRectangle rect = (CDSRectangle) array .getAttribute(CDSRectangle.class); if (rect == null) { rect = new CDSRectangle(array); array.setAttribute(CDSRectangle.class, rect); } return rect; } private Rectangle2D cachedRectangle; private Rectangle2D cachedNormalizedRectangle; /** * CDTRectangle constructor comment. */ public CDSRectangle() { super(COSArray.createWith(0, 0, 0, 0)); } /** * CDTRectangle constructor. Create a new rectangle with given array. * * @param newR * A four dimensional COSArray defining llx,lly, urx, ury. */ protected CDSRectangle(COSArray newR) { super(newR); } /** * CDTRectangle constructor. Create a new rectangle with given size. * * @param llx * the lower left x * @param lly * the lower left y * @param urx * the upper right x * @param ury * the upper right y */ public CDSRectangle(float llx, float lly, float urx, float ury) { super(COSArray.createWith(llx, lly, urx, ury)); } /** * CDTRectangle constructor. Create a new rectangle with given array. The * array must have 4 elements of type float. * * @param rectArray * A four dimensional array defining llx,lly, urx, ury. * * @see CDSRectangle#CDSRectangle(float llx, float lly, float urx, float * ury) */ public CDSRectangle(float[] rectArray) { this(rectArray[0], rectArray[1], rectArray[2], rectArray[3]); } public CDSRectangle(Rectangle2D rect) { super(COSArray.createWith((float) rect.getMinX(), (float) rect .getMinY(), (float) rect.getMaxX(), (float) rect.getMaxY())); } /** * true if x/y lies within this. * * @param x * x coordinate to be checked. * @param y * y coordinate to be checked. * @return true if x/y lies within this. */ public boolean contains(double x, double y) { COSArray array = cosGetArray(); float x0 = ((COSNumber) array.get(0)).floatValue(); float x1 = ((COSNumber) array.get(2)).floatValue(); if (x0 < x1) { if ((x < x0) || (x > x1)) { return false; } } else { if ((x > x0) || (x < x1)) { return false; } } float y0 = ((COSNumber) array.get(1)).floatValue(); float y1 = ((COSNumber) array.get(3)).floatValue(); if (y0 < y1) { return ((y >= y0) && (y <= y1)); } else { return ((y >= y1) && (y <= y0)); } } /** * true if x/y lies within this, with a "uncertainty" of * epsilon. * * @param x * x coordinate to be checked. * @param y * y coordinate to be checked. * @param epsilon * The allowed range of uncertainty * * @return true if x/y lies within this. */ public boolean contains(double x, double y, double epsilon) { COSArray array = cosGetArray(); float x0 = ((COSNumber) array.get(0)).floatValue(); float x1 = ((COSNumber) array.get(2)).floatValue(); if (x0 < x1) { if ((x < (x0 - epsilon)) || (x > (x1 + epsilon))) { return false; } } else { if ((x > (x0 + epsilon)) || (x < (x1 - epsilon))) { return false; } } float y0 = ((COSNumber) array.get(1)).floatValue(); float y1 = ((COSNumber) array.get(3)).floatValue(); if (y0 < y1) { return ((y >= (y0 - epsilon)) && (y <= (y1 + epsilon))); } else { return ((y >= (y1 - epsilon)) && (y <= (y0 + epsilon))); } } /** * Create a copy of the receiver * * @return a new copy of the receiver */ public CDSRectangle copy() { return new CDSRectangle((COSArray) cosGetArray().copyShallow()); } /** * Return the height (an absolute value) of the rectangle. * * @return Return the height (an absolute value) of the rectangle. */ public float getHeight() { return Math.abs(getUpperRightY() - getLowerLeftY()); } /** * The lower left x coordinate. * * @return The lower left x coordinate. */ public float getLowerLeftX() { return ((COSNumber) cosGetArray().get(0)).floatValue(); } /** * The lower left y coordinate. * * @return The lower left y coordinate. */ public float getLowerLeftY() { return ((COSNumber) cosGetArray().get(1)).floatValue(); } /** * The upper right x coordinate. * * @return The upper right x coordinate. */ public float getUpperRightX() { return ((COSNumber) cosGetArray().get(2)).floatValue(); } /** * The upper right y coordinate. * * @return The upper right y coordinate. */ public float getUpperRightY() { return ((COSNumber) cosGetArray().get(3)).floatValue(); } /** * Get the width (an absolute value) of the rectangle. * * @return Get the width (an absolute value) of the rectangle. */ public float getWidth() { return Math.abs(getUpperRightX() - getLowerLeftX()); } /* * (non-Javadoc) * * @see de.intarsys.pdf.cos.COSBasedObject#invalidateCaches() */ @Override public void invalidateCaches() { super.invalidateCaches(); cachedNormalizedRectangle = null; cachedRectangle = null; } /** * Move the rectangle by a relative offset. The relationship of the opposite * corners is preserved by this method. * * @param dx * The offset by which we move in x direction. * @param dy * The offset by which we move in y direction. */ public void move(float dx, float dy) { setLowerLeftX(getLowerLeftX() + dx); setLowerLeftY(getLowerLeftY() + dy); setUpperRightX(getUpperRightX() + dx); setUpperRightY(getUpperRightY() + dy); } /** * Move the rectangle to a new absolute position. The relationship of the * opposite corners is preserved by this method. The receiver is modified. * * @param x * The new x position of the lower left corner. * @param y * The new y position of the lower left corner. * * @return this */ public CDSRectangle moveTo(float x, float y) { float width = getUpperRightX() - getLowerLeftX(); float height = getUpperRightY() - getLowerLeftY(); setLowerLeftX(x); setLowerLeftY(y); setUpperRightX(width + x); setUpperRightY(height + y); return this; } /** * Adjust the corner coordinates so that lower left is really in the lower * left (this means returns the smallest coordinate values). * *

* This method changes this in place! *

* * @return this */ public CDSRectangle normalize() { float t1; float t2; if ((t1 = getLowerLeftX()) > (t2 = getUpperRightX())) { setLowerLeftX(t2); setUpperRightX(t1); } if ((t1 = getLowerLeftY()) > (t2 = getUpperRightY())) { setLowerLeftY(t2); setUpperRightY(t1); } return this; } /** * Resize the rectangle by moving the upper right corner. * * @param dx * The distance we move the upper right x coordinate. * @param dy * The distance we move the upper right y coordinate. */ public void resize(float dx, float dy) { setUpperRightX(getUpperRightX() + dx); setUpperRightY(getUpperRightY() + dy); } /** * Resize the rectangle to a new width and heigth. The new width and heigth * are defined relative to the lower left corner as signed values. * * @param width * The new width of the rectangle. * @param height * The new height of the rectangle. */ public void resizeTo(float width, float height) { setUpperRightX(getLowerLeftX() + width); setUpperRightY(getLowerLeftY() + height); } /** * Set the corners of this. * * @param llx * The lower left x coordinate * @param lly * The lower left y coordinate * @param urx * The upper right x coordinate * @param ury * The upper right y coordinate */ public void setCorners(float llx, float lly, float urx, float ury) { cosGetArray().set(0, COSFixed.create(llx)); cosGetArray().set(1, COSFixed.create(lly)); cosGetArray().set(2, COSFixed.create(urx)); cosGetArray().set(3, COSFixed.create(ury)); } /** * Set the height of this. * * @param height * THe new height */ public void setHeight(float height) { setUpperRightY(getLowerLeftY() + height); } /** * Set the lower left x coordinate. * * @param num * The lower left x coordinate. */ public void setLowerLeftX(float num) { cosGetArray().set(0, COSFixed.create(num)); } /** * Set the lower left y coordinate. * * @param num * The lower left y coordinate. */ public void setLowerLeftY(float num) { cosGetArray().set(1, COSFixed.create(num)); } /** * Set the upper right x coordinate. * * @param num * The upper right x coordinate. */ public void setUpperRightX(float num) { cosGetArray().set(2, COSFixed.create(num)); } /** * Set the upper right y coordinate. * * @param num * The upper right y coordinate. */ public void setUpperRightY(float num) { cosGetArray().set(3, COSFixed.create(num)); } /** * Set the width of this. * * @param width * The new width. */ public void setWidth(float width) { setUpperRightX(getLowerLeftX() + width); } public float[] toArray() { return new float[] { getLowerLeftX(), getLowerLeftY(), getUpperRightX(), getUpperRightY() }; } /** * Construct a {@link Rectangle2D} object from the receiver. The rectangle * will be normalized before construction. * * @return The Rectangle2D created from the receiver. */ public Rectangle2D toNormalizedRectangle() { if (cachedNormalizedRectangle == null) { float llx = getLowerLeftX(); float lly = getLowerLeftY(); float urx = getUpperRightX(); float ury = getUpperRightY(); float temp; if (llx > urx) { temp = llx; llx = urx; urx = temp; } if (lly > ury) { temp = lly; lly = ury; ury = temp; } cachedNormalizedRectangle = new Rectangle2D.Float(llx, lly, urx - llx, ury - lly); } return (Rectangle2D) cachedNormalizedRectangle.clone(); } /** * Construct a {@link Rectangle2D} object from the receiver. The resulting * rectangle is not normalized, that means it may return a negative width or * height. * * @return The Rectangle2D created from the receiver. */ public Rectangle2D toRectangle() { if (cachedRectangle == null) { float llx = getLowerLeftX(); float lly = getLowerLeftY(); float urx = getUpperRightX(); float ury = getUpperRightY(); cachedRectangle = new Rectangle2D.Float(llx, lly, urx - llx, ury - lly); } return (Rectangle2D) cachedRectangle.clone(); } }




© 2015 - 2024 Weber Informatics LLC | Privacy Policy