001/*
002 * $Id: Rectangle.java 4871 2011-05-13 19:05:12Z blowagie $
003 *
004 * This file is part of the iText (R) project.
005 * Copyright (c) 1998-2011 1T3XT BVBA
006 * Authors: Bruno Lowagie, Paulo Soares, et al.
007 *
008 * This program is free software; you can redistribute it and/or modify
009 * it under the terms of the GNU Affero General Public License version 3
010 * as published by the Free Software Foundation with the addition of the
011 * following permission added to Section 15 as permitted in Section 7(a):
012 * FOR ANY PART OF THE COVERED WORK IN WHICH THE COPYRIGHT IS OWNED BY 1T3XT,
013 * 1T3XT DISCLAIMS THE WARRANTY OF NON INFRINGEMENT OF THIRD PARTY RIGHTS.
014 *
015 * This program is distributed in the hope that it will be useful, but
016 * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
017 * or FITNESS FOR A PARTICULAR PURPOSE.
018 * See the GNU Affero General Public License for more details.
019 * You should have received a copy of the GNU Affero General Public License
020 * along with this program; if not, see http://www.gnu.org/licenses or write to
021 * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
022 * Boston, MA, 02110-1301 USA, or download the license from the following URL:
023 * http://itextpdf.com/terms-of-use/
024 *
025 * The interactive user interfaces in modified source and object code versions
026 * of this program must display Appropriate Legal Notices, as required under
027 * Section 5 of the GNU Affero General Public License.
028 *
029 * In accordance with Section 7(b) of the GNU Affero General Public License,
030 * a covered work must retain the producer line in every PDF that is created
031 * or manipulated using iText.
032 *
033 * You can be released from the requirements of the license by purchasing
034 * a commercial license. Buying such a license is mandatory as soon as you
035 * develop commercial activities involving the iText software without
036 * disclosing the source code of your own applications.
037 * These activities include: offering paid services to customers as an ASP,
038 * serving PDFs on the fly in a web application, shipping iText with a closed
039 * source product.
040 *
041 * For more information, please contact iText Software Corp. at this
042 * address: sales@itextpdf.com
043 */
044package com.itextpdf.text;
045
046import java.util.List;
047import java.util.ArrayList;
048
049import com.itextpdf.text.pdf.GrayColor;
050
051/**
052 * A <CODE>Rectangle</CODE> is the representation of a geometric figure.
053 *
054 * Rectangles support constant width borders using
055 * {@link #setBorderWidth(float)}and {@link #setBorder(int)}.
056 * They also support borders that vary in width/color on each side using
057 * methods like {@link #setBorderWidthLeft(float)}or
058 * {@link #setBorderColorLeft(BaseColor)}.
059 *
060 * @see Element
061 */
062public class Rectangle implements Element {
063
064        // CONSTANTS:
065
066        /** This is the value that will be used as <VAR>undefined </VAR>. */
067        public static final int UNDEFINED = -1;
068
069        /** This represents one side of the border of the <CODE>Rectangle</CODE>. */
070        public static final int TOP = 1;
071
072        /** This represents one side of the border of the <CODE>Rectangle</CODE>. */
073        public static final int BOTTOM = 2;
074
075        /** This represents one side of the border of the <CODE>Rectangle</CODE>. */
076        public static final int LEFT = 4;
077
078        /** This represents one side of the border of the <CODE>Rectangle</CODE>. */
079        public static final int RIGHT = 8;
080
081        /** This represents a rectangle without borders. */
082        public static final int NO_BORDER = 0;
083
084        /** This represents a type of border. */
085        public static final int BOX = TOP + BOTTOM + LEFT + RIGHT;
086
087        // MEMBER VARIABLES:
088
089        /** the lower left x-coordinate. */
090        protected float llx;
091
092        /** the lower left y-coordinate. */
093        protected float lly;
094
095        /** the upper right x-coordinate. */
096        protected float urx;
097
098        /** the upper right y-coordinate. */
099        protected float ury;
100
101        /** The rotation of the Rectangle */
102        protected int rotation = 0;
103
104        /** This is the color of the background of this rectangle. */
105        protected BaseColor backgroundColor = null;
106
107        /** This represents the status of the 4 sides of the rectangle. */
108        protected int border = UNDEFINED;
109
110        /** Whether variable width/color borders are used. */
111        protected boolean useVariableBorders = false;
112
113        /** This is the width of the border around this rectangle. */
114        protected float borderWidth = UNDEFINED;
115
116        /** The width of the left border of this rectangle. */
117        protected float borderWidthLeft = UNDEFINED;
118
119        /** The width of the right border of this rectangle. */
120        protected float borderWidthRight = UNDEFINED;
121
122        /** The width of the top border of this rectangle. */
123        protected float borderWidthTop = UNDEFINED;
124
125        /** The width of the bottom border of this rectangle. */
126        protected float borderWidthBottom = UNDEFINED;
127
128        /** The color of the border of this rectangle. */
129        protected BaseColor borderColor = null;
130
131        /** The color of the left border of this rectangle. */
132        protected BaseColor borderColorLeft = null;
133
134        /** The color of the right border of this rectangle. */
135        protected BaseColor borderColorRight = null;
136
137        /** The color of the top border of this rectangle. */
138        protected BaseColor borderColorTop = null;
139
140        /** The color of the bottom border of this rectangle. */
141        protected BaseColor borderColorBottom = null;
142
143        // CONSTRUCTORS:
144
145        /**
146         * Constructs a <CODE>Rectangle</CODE> -object.
147         *
148         * @param llx   lower left x
149         * @param lly   lower left y
150         * @param urx   upper right x
151         * @param ury   upper right y
152         */
153        public Rectangle(final float llx, final float lly, final float urx, final float ury) {
154                this.llx = llx;
155                this.lly = lly;
156                this.urx = urx;
157                this.ury = ury;
158        }
159
160        /**
161         * Constructs a <CODE>Rectangle</CODE>-object.
162         *
163         * @param llx   lower left x
164         * @param lly   lower left y
165         * @param urx   upper right x
166         * @param ury   upper right y
167         * @param rotation the rotation (0, 90, 180, or 270)
168         * @since iText 5.0.6
169         */
170        public Rectangle(final float llx, final float lly, final float urx, final float ury, final int rotation) {
171                this(llx, lly, urx, ury);
172                setRotation(rotation);
173        }
174
175        /**
176         * Constructs a <CODE>Rectangle</CODE> -object starting from the origin
177         * (0, 0).
178         *
179         * @param urx   upper right x
180         * @param ury   upper right y
181         */
182        public Rectangle(final float urx, final float ury) {
183                this(0, 0, urx, ury);
184        }
185
186        /**
187         * Constructs a <CODE>Rectangle</CODE>-object starting from the origin
188         * (0, 0) and with a specific rotation (valid values are 0, 90, 180, 270).
189         *
190         * @param urx   upper right x
191         * @param ury   upper right y
192         * @param rotation the rotation of the rectangle
193         * @since iText 5.0.6
194         */
195        public Rectangle(final float urx, final float ury, final int rotation) {
196                this(0, 0, urx, ury, rotation);
197        }
198
199        /**
200         * Constructs a <CODE>Rectangle</CODE> -object.
201         *
202         * @param rect  another <CODE>Rectangle</CODE>
203         */
204        public Rectangle(final Rectangle rect) {
205                this(rect.llx, rect.lly, rect.urx, rect.ury);
206                cloneNonPositionParameters(rect);
207        }
208
209        // IMPLEMENTATION OF THE ELEMENT INTERFACE:e
210
211        /**
212         * Processes the element by adding it (or the different parts) to an
213         * <CODE>ElementListener</CODE>.
214         *
215         * @param listener      an <CODE>ElementListener</CODE>
216         * @return <CODE>true</CODE> if the element was processed successfully
217         */
218        public boolean process(final ElementListener listener) {
219                try {
220                        return listener.add(this);
221                }
222                catch (DocumentException de) {
223                        return false;
224                }
225        }
226
227        /**
228         * Gets the type of the text element.
229         *
230         * @return a type
231         */
232        public int type() {
233                return Element.RECTANGLE;
234        }
235
236        /**
237         * Gets all the chunks in this element.
238         *
239         * @return an <CODE>ArrayList</CODE>
240         */
241        public List<Chunk> getChunks() {
242                return new ArrayList<Chunk>();
243        }
244
245        /**
246         * @see com.itextpdf.text.Element#isContent()
247         * @since       iText 2.0.8
248         */
249        public boolean isContent() {
250                return true;
251        }
252
253        /**
254         * @see com.itextpdf.text.Element#isNestable()
255         * @since       iText 2.0.8
256         */
257        public boolean isNestable() {
258                return false;
259        }
260
261        // METHODS TO GET/SET THE DIMENSIONS:
262
263        /**
264         * Sets the lower left x-coordinate.
265         *
266         * @param llx   the new value
267         */
268        public void setLeft(final float llx) {
269                this.llx = llx;
270        }
271
272        /**
273         * Returns the lower left x-coordinate.
274         *
275         * @return the lower left x-coordinate
276         */
277        public float getLeft() {
278                return llx;
279        }
280
281        /**
282         * Returns the lower left x-coordinate, considering a given margin.
283         *
284         * @param margin        a margin
285         * @return the lower left x-coordinate
286         */
287        public float getLeft(final float margin) {
288                return llx + margin;
289        }
290
291        /**
292         * Sets the upper right x-coordinate.
293         *
294         * @param urx   the new value
295         */
296        public void setRight(final float urx) {
297                this.urx = urx;
298        }
299
300        /**
301         * Returns the upper right x-coordinate.
302         *
303         * @return the upper right x-coordinate
304         */
305        public float getRight() {
306                return urx;
307        }
308
309        /**
310         * Returns the upper right x-coordinate, considering a given margin.
311         *
312         * @param margin        a margin
313         * @return the upper right x-coordinate
314         */
315        public float getRight(final float margin) {
316                return urx - margin;
317        }
318
319        /**
320         * Returns the width of the rectangle.
321         *
322         * @return      the width
323         */
324        public float getWidth() {
325                return urx - llx;
326        }
327
328        /**
329         * Sets the upper right y-coordinate.
330         *
331         * @param ury   the new value
332         */
333        public void setTop(final float ury) {
334                this.ury = ury;
335        }
336
337        /**
338         * Returns the upper right y-coordinate.
339         *
340         * @return the upper right y-coordinate
341         */
342        public float getTop() {
343                return ury;
344        }
345
346        /**
347         * Returns the upper right y-coordinate, considering a given margin.
348         *
349         * @param margin        a margin
350         * @return the upper right y-coordinate
351         */
352        public float getTop(final float margin) {
353                return ury - margin;
354        }
355
356        /**
357         * Sets the lower left y-coordinate.
358         *
359         * @param lly   the new value
360         */
361        public void setBottom(final float lly) {
362                this.lly = lly;
363        }
364
365        /**
366         * Returns the lower left y-coordinate.
367         *
368         * @return the lower left y-coordinate
369         */
370        public float getBottom() {
371                return lly;
372        }
373
374        /**
375         * Returns the lower left y-coordinate, considering a given margin.
376         *
377         * @param margin        a margin
378         * @return the lower left y-coordinate
379         */
380        public float getBottom(final float margin) {
381                return lly + margin;
382        }
383
384        /**
385         * Returns the height of the rectangle.
386         *
387         * @return the height
388         */
389        public float getHeight() {
390                return ury - lly;
391        }
392
393        /**
394         * Normalizes the rectangle.
395         * Switches lower left with upper right if necessary.
396         */
397        public void normalize() {
398                if (llx > urx) {
399                        float a = llx;
400                        llx = urx;
401                        urx = a;
402                }
403                if (lly > ury) {
404                        float a = lly;
405                        lly = ury;
406                        ury = a;
407                }
408        }
409
410        // METHODS TO GET/SET THE ROTATION:
411
412        /**
413         * Gets the rotation of the rectangle
414         *
415         * @return a rotation value
416         */
417        public int getRotation() {
418                return rotation;
419        }
420
421        /**
422         * Sets the rotation of the rectangle. Valid values are 0, 90, 180, and 270.
423         * @param rotation the new rotation value
424         * @since iText 5.0.6
425         */
426        public void setRotation(final int rotation) {
427                this.rotation = rotation % 360;
428                switch (this.rotation) {
429                case 90:
430                case 180:
431                case 270:
432            break;
433        default:
434                        this.rotation = 0;
435                }
436        }
437
438        /**
439         * Rotates the rectangle.
440         * Swaps the values of llx and lly and of urx and ury.
441         *
442         * @return the rotated <CODE>Rectangle</CODE>
443         */
444        public Rectangle rotate() {
445                Rectangle rect = new Rectangle(lly, llx, ury, urx);
446                rect.setRotation(rotation + 90);
447                return rect;
448        }
449
450        // METHODS TO GET/SET THE BACKGROUND COLOR:
451
452        /**
453         * Gets the backgroundcolor.
454         *
455         * @return a <CODE>BaseColor</CODE>
456         */
457        public BaseColor getBackgroundColor() {
458                return backgroundColor;
459        }
460
461        /**
462         * Sets the backgroundcolor of the rectangle.
463         *
464         * @param backgroundColor       a <CODE>BaseColor</CODE>
465         */
466
467        public void setBackgroundColor(final BaseColor backgroundColor) {
468                this.backgroundColor = backgroundColor;
469        }
470
471        /**
472         * Gets the grayscale.
473         *
474         * @return the grayscale color of the background
475     * or 0 if the background has no grayscale color.
476         */
477        public float getGrayFill() {
478        if (backgroundColor instanceof GrayColor)
479            return ((GrayColor)backgroundColor).getGray();
480        return 0;
481        }
482
483        /**
484         * Sets the the background color to a grayscale value.
485         *
486         * @param value the new grayscale value
487         */
488        public void setGrayFill(final float value) {
489        backgroundColor = new GrayColor(value);
490        }
491
492//       METHODS TO GET/SET THE BORDER:
493
494        /**
495         * Returns the exact type of the border.
496         *
497         * @return a value
498         */
499        public int getBorder() {
500                return border;
501        }
502
503        /**
504         * Indicates whether some type of border is set.
505         *
506         * @return a boolean
507         */
508        public boolean hasBorders() {
509                switch (border) {
510                        case UNDEFINED:
511                        case NO_BORDER:
512                                return false;
513                        default:
514                                return borderWidth > 0 || borderWidthLeft > 0
515                                                || borderWidthRight > 0 || borderWidthTop > 0 || borderWidthBottom > 0;
516                }
517        }
518
519        /**
520         * Indicates whether the specified type of border is set.
521         *
522         * @param type  the type of border
523         * @return a boolean
524         */
525        public boolean hasBorder(final int type) {
526                if (border == UNDEFINED)
527                        return false;
528                return (border & type) == type;
529        }
530
531        /**
532         * Enables/Disables the border on the specified sides.
533         * The border is specified as an integer bitwise combination of
534         * the constants: <CODE>LEFT, RIGHT, TOP, BOTTOM</CODE>.
535         *
536         * @see #enableBorderSide(int)
537         * @see #disableBorderSide(int)
538         * @param border        the new value
539         */
540        public void setBorder(final int border) {
541                this.border = border;
542        }
543
544        /**
545         * Indicates whether variable width borders are being used.
546         * Returns true if <CODE>setBorderWidthLeft, setBorderWidthRight,
547         * setBorderWidthTop, or setBorderWidthBottom</CODE> has been called.
548         *
549         * @return true if variable width borders are in use
550         */
551        public boolean isUseVariableBorders() {
552                return useVariableBorders;
553        }
554
555        /**
556         * Sets a parameter indicating if the rectangle has variable borders
557         *
558         * @param useVariableBorders indication if the rectangle has variable borders
559         */
560        public void setUseVariableBorders(final boolean useVariableBorders) {
561                this.useVariableBorders = useVariableBorders;
562        }
563
564        /**
565         * Enables the border on the specified side.
566         *
567         * @param side  the side to enable.
568         * One of <CODE>LEFT, RIGHT, TOP, BOTTOM</CODE>
569         */
570        public void enableBorderSide(final int side) {
571                if (border == UNDEFINED)
572                        border = 0;
573                border |= side;
574        }
575
576        /**
577         * Disables the border on the specified side.
578         *
579         * @param side  the side to disable.
580         * One of <CODE>LEFT, RIGHT, TOP, BOTTOM</CODE>
581         */
582        public void disableBorderSide(final int side) {
583                if (border == UNDEFINED)
584                        border = 0;
585                border &= ~side;
586        }
587
588        // METHODS TO GET/SET THE BORDER WIDTH:
589
590        /**
591         * Gets the borderwidth.
592         *
593         * @return a value
594         */
595        public float getBorderWidth() {
596                return borderWidth;
597        }
598
599        /**
600         * Sets the borderwidth of the table.
601         *
602         * @param borderWidth the new value
603         */
604        public void setBorderWidth(final float borderWidth) {
605                this.borderWidth = borderWidth;
606        }
607
608        /**
609         * Helper function returning the border width of a specific side.
610         *
611         * @param       variableWidthValue      a variable width (could be undefined)
612         * @param       side    the border you want to check
613         * @return      the variableWidthValue if not undefined, otherwise the borderWidth
614         */
615        private float getVariableBorderWidth(final float variableWidthValue, final int side) {
616                if ((border & side) != 0)
617                        return variableWidthValue != UNDEFINED ? variableWidthValue : borderWidth;
618                return 0;
619        }
620
621        /**
622         * Helper function updating the border flag for a side
623         * based on the specified width.
624         * A width of 0 will disable the border on that side.
625         * Any other width enables it.
626         *
627         * @param width width of border
628         * @param side  border side constant
629         */
630        private void updateBorderBasedOnWidth(final float width, final int side) {
631                useVariableBorders = true;
632                if (width > 0)
633                        enableBorderSide(side);
634                else
635                        disableBorderSide(side);
636        }
637
638        /**
639         * Gets the width of the left border.
640         *
641         * @return a width
642         */
643        public float getBorderWidthLeft() {
644                return getVariableBorderWidth(borderWidthLeft, LEFT);
645        }
646
647        /**
648         * Sets the width of the left border.
649         *
650         * @param borderWidthLeft a width
651         */
652        public void setBorderWidthLeft(final float borderWidthLeft) {
653                this.borderWidthLeft = borderWidthLeft;
654                updateBorderBasedOnWidth(borderWidthLeft, LEFT);
655        }
656
657        /**
658         * Gets the width of the right border.
659         *
660         * @return a width
661         */
662        public float getBorderWidthRight() {
663                return getVariableBorderWidth(borderWidthRight, RIGHT);
664        }
665
666        /**
667         * Sets the width of the right border.
668         *
669         * @param borderWidthRight a width
670         */
671        public void setBorderWidthRight(final float borderWidthRight) {
672                this.borderWidthRight = borderWidthRight;
673                updateBorderBasedOnWidth(borderWidthRight, RIGHT);
674        }
675
676        /**
677         * Gets the width of the top border.
678         *
679         * @return a width
680         */
681        public float getBorderWidthTop() {
682                return getVariableBorderWidth(borderWidthTop, TOP);
683        }
684
685        /**
686         * Sets the width of the top border.
687         *
688         * @param borderWidthTop a width
689         */
690        public void setBorderWidthTop(final float borderWidthTop) {
691                this.borderWidthTop = borderWidthTop;
692                updateBorderBasedOnWidth(borderWidthTop, TOP);
693        }
694
695        /**
696         * Gets the width of the bottom border.
697         *
698         * @return a width
699         */
700        public float getBorderWidthBottom() {
701                return getVariableBorderWidth(borderWidthBottom, BOTTOM);
702        }
703
704        /**
705         * Sets the width of the bottom border.
706         *
707         * @param borderWidthBottom a width
708         */
709        public void setBorderWidthBottom(final float borderWidthBottom) {
710                this.borderWidthBottom = borderWidthBottom;
711                updateBorderBasedOnWidth(borderWidthBottom, BOTTOM);
712        }
713
714        // METHODS TO GET/SET THE BORDER COLOR:
715
716        /**
717         * Gets the color of the border.
718         *
719         * @return      a <CODE>BaseColor</CODE>
720         */
721        public BaseColor getBorderColor() {
722                return borderColor;
723        }
724
725        /**
726         * Sets the color of the border.
727         *
728         * @param borderColor a <CODE>BaseColor</CODE>
729         */
730        public void setBorderColor(final BaseColor borderColor) {
731                this.borderColor = borderColor;
732        }
733
734        /**
735         * Gets the color of the left border.
736         *
737         * @return a <CODE>BaseColor</CODE>
738         */
739        public BaseColor getBorderColorLeft() {
740                if (borderColorLeft == null)
741                        return borderColor;
742                return borderColorLeft;
743        }
744
745        /**
746         * Sets the color of the left border.
747         *
748         * @param borderColorLeft a <CODE>BaseColor</CODE>
749         */
750        public void setBorderColorLeft(final BaseColor borderColorLeft) {
751                this.borderColorLeft = borderColorLeft;
752        }
753
754        /**
755         * Gets the color of the right border.
756         *
757         * @return a <CODE>BaseColor</CODE>
758         */
759        public BaseColor getBorderColorRight() {
760                if (borderColorRight == null)
761                        return borderColor;
762                return borderColorRight;
763        }
764
765        /**
766         * Sets the color of the right border.
767         *
768         * @param borderColorRight a <CODE>BaseColor</CODE>
769         */
770        public void setBorderColorRight(final BaseColor borderColorRight) {
771                this.borderColorRight = borderColorRight;
772        }
773
774        /**
775         * Gets the color of the top border.
776         *
777         * @return a <CODE>BaseColor</CODE>
778         */
779        public BaseColor getBorderColorTop() {
780                if (borderColorTop == null)
781                        return borderColor;
782                return borderColorTop;
783        }
784
785        /**
786         * Sets the color of the top border.
787         *
788         * @param borderColorTop a <CODE>BaseColor</CODE>
789         */
790        public void setBorderColorTop(final BaseColor borderColorTop) {
791                this.borderColorTop = borderColorTop;
792        }
793
794        /**
795         * Gets the color of the bottom border.
796         *
797         * @return a <CODE>BaseColor</CODE>
798         */
799        public BaseColor getBorderColorBottom() {
800                if (borderColorBottom == null)
801                        return borderColor;
802                return borderColorBottom;
803        }
804
805        /**
806         * Sets the color of the bottom border.
807         *
808         * @param borderColorBottom a <CODE>BaseColor</CODE>
809         */
810        public void setBorderColorBottom(final BaseColor borderColorBottom) {
811                this.borderColorBottom = borderColorBottom;
812        }
813
814        // SPECIAL METHODS:
815
816        /**
817         * Gets a Rectangle that is altered to fit on the page.
818         *
819         * @param top           the top position
820         * @param bottom        the bottom position
821         * @return a <CODE>Rectangle</CODE>
822         */
823        public Rectangle rectangle(final float top, final float bottom) {
824                Rectangle tmp = new Rectangle(this);
825                if (getTop() > top) {
826                        tmp.setTop(top);
827                        tmp.disableBorderSide(TOP);
828                }
829                if (getBottom() < bottom) {
830                        tmp.setBottom(bottom);
831                        tmp.disableBorderSide(BOTTOM);
832                }
833                return tmp;
834        }
835
836        /**
837         * Copies each of the parameters, except the position, from a
838         * <CODE>Rectangle</CODE> object
839         *
840         * @param rect  <CODE>Rectangle</CODE> to copy from
841         */
842        public void cloneNonPositionParameters(final Rectangle rect) {
843                this.rotation = rect.rotation;
844                this.backgroundColor = rect.backgroundColor;
845                this.border = rect.border;
846                this.useVariableBorders = rect.useVariableBorders;
847                this.borderWidth = rect.borderWidth;
848                this.borderWidthLeft = rect.borderWidthLeft;
849                this.borderWidthRight = rect.borderWidthRight;
850                this.borderWidthTop = rect.borderWidthTop;
851                this.borderWidthBottom = rect.borderWidthBottom;
852                this.borderColor = rect.borderColor;
853                this.borderColorLeft = rect.borderColorLeft;
854                this.borderColorRight = rect.borderColorRight;
855                this.borderColorTop = rect.borderColorTop;
856                this.borderColorBottom = rect.borderColorBottom;
857        }
858
859        /**
860         * Copies each of the parameters, except the position, from a
861         * <CODE>Rectangle</CODE> object if the value is set there
862         *
863         * @param rect <CODE>Rectangle</CODE> to copy from
864         */
865        public void softCloneNonPositionParameters(final Rectangle rect) {
866                if (rect.rotation != 0)
867                        this.rotation = rect.rotation;
868                if (rect.backgroundColor != null)
869                        this.backgroundColor = rect.backgroundColor;
870                if (rect.border != UNDEFINED)
871                        this.border = rect.border;
872                if (useVariableBorders)
873                        this.useVariableBorders = rect.useVariableBorders;
874                if (rect.borderWidth != UNDEFINED)
875                        this.borderWidth = rect.borderWidth;
876                if (rect.borderWidthLeft != UNDEFINED)
877                        this.borderWidthLeft = rect.borderWidthLeft;
878                if (rect.borderWidthRight != UNDEFINED)
879                        this.borderWidthRight = rect.borderWidthRight;
880                if (rect.borderWidthTop != UNDEFINED)
881                        this.borderWidthTop = rect.borderWidthTop;
882                if (rect.borderWidthBottom != UNDEFINED)
883                        this.borderWidthBottom = rect.borderWidthBottom;
884                if (rect.borderColor != null)
885                        this.borderColor = rect.borderColor;
886                if (rect.borderColorLeft != null)
887                        this.borderColorLeft = rect.borderColorLeft;
888                if (rect.borderColorRight != null)
889                        this.borderColorRight = rect.borderColorRight;
890                if (rect.borderColorTop != null)
891                        this.borderColorTop = rect.borderColorTop;
892                if (rect.borderColorBottom != null)
893                        this.borderColorBottom = rect.borderColorBottom;
894        }
895
896        /**
897         * @return      a String representation of the rectangle
898         * @see java.lang.Object#toString()
899         */
900        @Override
901    public String toString() {
902                StringBuffer buf = new StringBuffer("Rectangle: ");
903                buf.append(getWidth());
904                buf.append('x');
905                buf.append(getHeight());
906                buf.append(" (rot: ");
907                buf.append(rotation);
908                buf.append(" degrees)");
909                return buf.toString();
910        }
911
912}